Skip to content

Commit f088854

Browse files
authored
[message-buffer 15/x] - audit fixes (#817)
* fix(message-buffer): set payer as admin in initialize (TOB-PYTH-5) * fix(message-buffer/delete_buffer): remove auth validation in delete_buffer & add test (TOB-PYTH-7) * fix(message-buffer): fix non-security-related findings use constant for seeds, cap max target size, add more tests * refactor(message-buffer): use seed consts in initialize, remove unused errors * refactor(message-buffer): address PR comments refactor missed consts, make initialize more readable
1 parent 3b03f9e commit f088854

File tree

13 files changed

+287
-111
lines changed

13 files changed

+287
-111
lines changed

pythnet/message_buffer/programs/message_buffer/src/instructions/create_buffer.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use {
44
state::*,
55
MessageBufferError,
66
MESSAGE,
7+
WHITELIST,
78
},
89
anchor_lang::{
910
prelude::*,
@@ -23,6 +24,8 @@ pub fn create_buffer<'info>(
2324
base_account_key: Pubkey,
2425
target_size: u32,
2526
) -> Result<()> {
27+
require_keys_neq!(base_account_key, Pubkey::default());
28+
2629
let buffer_account = ctx
2730
.remaining_accounts
2831
.first()
@@ -86,9 +89,9 @@ pub fn create_buffer<'info>(
8689
#[derive(Accounts)]
8790
pub struct CreateBuffer<'info> {
8891
#[account(
89-
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
90-
bump = whitelist.bump,
91-
has_one = admin,
92+
seeds = [MESSAGE.as_bytes(), WHITELIST.as_bytes()],
93+
bump = whitelist.bump,
94+
has_one = admin,
9295
)]
9396
pub whitelist: Account<'info, Whitelist>,
9497

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
use {
2-
crate::state::*,
2+
crate::{
3+
state::*,
4+
MESSAGE,
5+
WHITELIST,
6+
},
37
anchor_lang::prelude::*,
48
};
59

610
pub fn delete_buffer<'info>(
7-
ctx: Context<'_, '_, '_, 'info, DeleteBuffer<'info>>,
8-
allowed_program_auth: Pubkey,
11+
_ctx: Context<'_, '_, '_, 'info, DeleteBuffer<'info>>,
12+
_allowed_program_auth: Pubkey,
913
_base_account_key: Pubkey,
1014
) -> Result<()> {
11-
ctx.accounts
12-
.whitelist
13-
.is_allowed_program_auth(&allowed_program_auth)?;
1415
Ok(())
1516
}
1617

1718
#[derive(Accounts)]
1819
#[instruction(allowed_program_auth: Pubkey, base_account_key: Pubkey)]
1920
pub struct DeleteBuffer<'info> {
2021
#[account(
21-
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
22+
seeds = [MESSAGE.as_bytes(), WHITELIST.as_bytes()],
2223
bump = whitelist.bump,
2324
has_one = admin,
2425
)]
@@ -29,10 +30,10 @@ pub struct DeleteBuffer<'info> {
2930
pub admin: Signer<'info>,
3031

3132
#[account(
32-
mut,
33-
close = admin,
34-
seeds = [allowed_program_auth.as_ref(), b"message".as_ref(), base_account_key.as_ref()],
35-
bump = message_buffer.load()?.bump,
33+
mut,
34+
close = admin,
35+
seeds = [allowed_program_auth.as_ref(), MESSAGE.as_bytes(), base_account_key.as_ref()],
36+
bump = message_buffer.load()?.bump,
3637
)]
3738
pub message_buffer: AccountLoader<'info, MessageBuffer>,
3839
}

pythnet/message_buffer/programs/message_buffer/src/instructions/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod resize_buffer;
2121
// where authorized_program_pda is the where `allowed_program_auth`
2222
// is the whitelisted pubkey who authorized this call.
2323
pub const MESSAGE: &str = "message";
24+
pub const WHITELIST: &str = "whitelist";
2425

2526
pub fn is_uninitialized_account(ai: &AccountInfo) -> bool {
2627
ai.data_is_empty() && ai.owner == &system_program::ID

pythnet/message_buffer/programs/message_buffer/src/instructions/put_all.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use {
2-
crate::state::*,
2+
crate::{
3+
state::*,
4+
MESSAGE,
5+
},
36
anchor_lang::prelude::*,
47
};
58

@@ -33,7 +36,7 @@ pub struct PutAll<'info> {
3336
pub whitelist_verifier: WhitelistVerifier<'info>,
3437
#[account(
3538
mut,
36-
seeds = [whitelist_verifier.cpi_caller_auth.key().as_ref(), b"message".as_ref(), base_account_key.as_ref()],
39+
seeds = [whitelist_verifier.cpi_caller_auth.key().as_ref(), MESSAGE.as_bytes(), base_account_key.as_ref()],
3740
bump = message_buffer.load()?.bump,
3841
)]
3942
pub message_buffer: AccountLoader<'info, MessageBuffer>,

pythnet/message_buffer/programs/message_buffer/src/instructions/resize_buffer.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use {
22
crate::{
33
state::*,
44
MessageBufferError,
5+
MESSAGE,
6+
WHITELIST,
57
},
68
anchor_lang::prelude::*,
79
};
@@ -25,6 +27,13 @@ pub fn resize_buffer<'info>(
2527
minimum_size as usize,
2628
MessageBufferError::MessageBufferTooSmall
2729
);
30+
31+
require_gte!(
32+
MessageBuffer::MAX_LEN as usize,
33+
target_size as usize,
34+
MessageBufferError::TargetSizeExceedsMaxLen
35+
);
36+
2837
Ok(())
2938
}
3039

@@ -34,7 +43,7 @@ pub fn resize_buffer<'info>(
3443
)]
3544
pub struct ResizeBuffer<'info> {
3645
#[account(
37-
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
46+
seeds = [MESSAGE.as_bytes(), WHITELIST.as_bytes()],
3847
bump = whitelist.bump,
3948
has_one = admin,
4049
)]
@@ -47,15 +56,16 @@ pub struct ResizeBuffer<'info> {
4756
pub system_program: Program<'info, System>,
4857

4958
/// If decreasing, Anchor will automatically check
50-
/// if target_size is too small and if so,then load() will fail.
59+
/// if target_size is < MessageBuffer::INIT_SPACE + 8
60+
/// and if so,then load() will fail.
5161
/// If increasing, Anchor also automatically checks if target_size delta
5262
/// exceeds MAX_PERMITTED_DATA_INCREASE
5363
#[account(
5464
mut,
5565
realloc = target_size as usize,
5666
realloc::zero = false,
5767
realloc::payer = admin,
58-
seeds = [allowed_program_auth.as_ref(), b"message".as_ref(), base_account_key.as_ref()],
68+
seeds = [allowed_program_auth.as_ref(), MESSAGE.as_bytes(), base_account_key.as_ref()],
5969
bump = message_buffer.load()?.bump,
6070
)]
6171
pub message_buffer: AccountLoader<'info, MessageBuffer>,

pythnet/message_buffer/programs/message_buffer/src/lib.rs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
pub mod instructions;
2-
mod macros;
32
mod state;
43

54

65
use {
6+
crate::{
7+
MESSAGE,
8+
WHITELIST,
9+
},
710
anchor_lang::prelude::*,
811
instructions::*,
912
state::*,
@@ -16,13 +19,13 @@ pub mod message_buffer {
1619
use super::*;
1720

1821

19-
/// Initializes the whitelist and sets it's admin to the provided pubkey
20-
/// Once initialized, the authority must sign all further changes to the whitelist.
21-
pub fn initialize(ctx: Context<Initialize>, admin: Pubkey) -> Result<()> {
22-
require_keys_neq!(admin, Pubkey::default());
22+
/// Initializes the whitelist and sets it's admin. Once initialized,
23+
/// the admin must sign all further changes to the whitelist.
24+
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
25+
require_keys_neq!(ctx.accounts.admin.key(), Pubkey::default());
2326
let whitelist = &mut ctx.accounts.whitelist;
2427
whitelist.bump = *ctx.bumps.get("whitelist").unwrap();
25-
whitelist.admin = admin;
28+
whitelist.admin = ctx.accounts.admin.key();
2629
Ok(())
2730
}
2831

@@ -141,12 +144,13 @@ pub mod message_buffer {
141144

142145
#[derive(Accounts)]
143146
pub struct Initialize<'info> {
147+
/// Admin that can update the whitelist and create/resize/delete buffers
144148
#[account(mut)]
145-
pub payer: Signer<'info>,
149+
pub admin: Signer<'info>,
146150
#[account(
147151
init,
148-
payer = payer,
149-
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
152+
payer = admin,
153+
seeds = [MESSAGE.as_bytes(), WHITELIST.as_bytes()],
150154
bump,
151155
space = 8 + Whitelist::INIT_SPACE,
152156
)]
@@ -157,13 +161,10 @@ pub struct Initialize<'info> {
157161

158162
#[derive(Accounts)]
159163
pub struct UpdateWhitelist<'info> {
160-
#[account(mut)]
161-
pub payer: Signer<'info>,
162-
163164
pub admin: Signer<'info>,
164165
#[account(
165166
mut,
166-
seeds = [b"message".as_ref(), b"whitelist".as_ref()],
167+
seeds = [MESSAGE.as_bytes(), WHITELIST.as_bytes()],
167168
bump = whitelist.bump,
168169
has_one = admin
169170
)]
@@ -175,32 +176,16 @@ pub struct UpdateWhitelist<'info> {
175176
pub enum MessageBufferError {
176177
#[msg("CPI Caller not allowed")]
177178
CallerNotAllowed,
178-
#[msg("Whitelist already contains program")]
179-
DuplicateAllowedProgram,
180-
#[msg("Conversion Error")]
181-
ConversionError,
182-
#[msg("Serialization Error")]
183-
SerializeError,
184-
#[msg("Whitelist admin required on initialization")]
185-
WhitelistAdminRequired,
186179
#[msg("Invalid allowed program")]
187180
InvalidAllowedProgram,
188181
#[msg("Maximum number of allowed programs exceeded")]
189182
MaximumAllowedProgramsExceeded,
190-
#[msg("Invalid PDA")]
191-
InvalidPDA,
192-
#[msg("Update data exceeds current length")]
193-
CurrentDataLengthExceeded,
194183
#[msg("Message Buffer not provided")]
195184
MessageBufferNotProvided,
196185
#[msg("Message Buffer target size is not sufficiently large")]
197186
MessageBufferTooSmall,
198-
#[msg("Fund Bump not found")]
199-
FundBumpNotFound,
200-
#[msg("Reallocation failed")]
201-
ReallocFailed,
202187
#[msg("Target size too large for reallocation/initialization. Max delta is 10240")]
203188
TargetSizeDeltaExceeded,
204-
#[msg("MessageBuffer Uninitialized")]
205-
MessageBufferUninitialized,
189+
#[msg("Target size exceeds MessageBuffer::MAX_LEN")]
190+
TargetSizeExceedsMaxLen,
206191
}

pythnet/message_buffer/programs/message_buffer/src/macros.rs

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)