Skip to content

Add security.txt to the settlement program - #91

Closed
kaze-cow wants to merge 2 commits into
mainfrom
add-security-txt
Closed

Add security.txt to the settlement program#91
kaze-cow wants to merge 2 commits into
mainfrom
add-security-txt

Conversation

@kaze-cow

@kaze-cow kaze-cow commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Embeds machine-readable security contact information in the settlement program binary, following the security.txt standard for Solana programs.

Motivation

We are still missing one element on the etherscan display of the settlement program:

image

Fair note though, many other apparently very popular solana programs, such as Pump.fun AMM or Jupiter Aggregator programs, do NOT publish a security.txt (or a solana program verification, for that matter), so we could probably get a way with deploying without this if we really wanted to.

Considerations

programs/settlement/src/security_txt.rs inlines the macro definition rather than adding solana-security-txt as a dependency. Upstream is a single macro_rules! with no runtime code, so this produces identical output without adding supply chain surface to a program we compile on-chain.

source_revision / source_release are deliberately omitted. Upstream suggests populating them from the build environment, but that would make the binary depend on environment variables and break the byte-for-byte reproducibility just build-verified establishes. solana-verify already pins the deployed binary to a commit.

Test

tests/security_txt.rs naively scans the built .so to verify the presence of the security.txt section is included in the compiled .so program.

Verification

The .security.txt section now appears in the built artifact (16 bytes — a &str static is a fat pointer, so the section holds the pointer/length pair while the bytes stay in .rodata):

$ objdump -h target/deploy/cow_settlement.so
...
  2 .rodata       000007b7 0000000000009790 DATA
...
  5 .security.txt 00000010 000000000000a248 DATA

For the ultimate test--I verified it is recognized by the block explorer on our devnet Mooohh program.
image

🤖 Generated with Claude Code

Embed machine-readable security contact information in the program
binary, following the security.txt standard for Solana programs
(https://github.com/neodyme-labs/solana-security-txt). A researcher who
finds a problem typically has only the program address to go on; shipping
the contacts inside the binary means they can be recovered from the
deployed program alone.

The macro definition is copied into `programs/settlement` rather than
pulled in as a dependency: upstream is a single `macro_rules!` with no
runtime code, so inlining it produces the same output without adding
supply chain surface to a program we compile on-chain.

Two deviations from upstream worth noting:

- The `link_section` attribute is gated on `target_os = "solana"` rather
  than upstream's `target_arch = "bpf"`, which no longer matches any
  Solana target. `cargo build-sbf` builds for `sbpf-solana-solana`, which
  reports `target_arch = "sbf"`, so upstream's gate never fires and the
  `.security.txt` ELF section is silently dropped. Some gate is required
  because a bare section name is invalid on Mach-O hosts.
- `policy` carries free text instead of a link, so the one required field
  every parser surfaces also warns that this program is for testing only
  and should not be trusted with funds. The standard has no field for
  that, and a researcher reading the notice off a deployed program has no
  other way to learn it.

`source_revision`/`source_release` are deliberately omitted: populating
them from the build environment would make the binary depend on
environment variables and break the byte-for-byte reproducibility that
`just build-verified` establishes.

Add an integration test that naively scans the built .so for the standard
begin/end markers. The blob is never referenced from Rust, so nothing
about the host build proves it survives compilation and linking into the
deployed artifact — only reading the .so back does. The markers are
counted rather than merely located, since the standard requires them to
be unique for naive parsers to work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Aug 5, 2026

Copy link
Copy Markdown

SC-303

@kaze-cow
kaze-cow marked this pull request as ready for review August 6, 2026 06:53
@kaze-cow
kaze-cow requested a review from a team as a code owner August 6, 2026 06:53

@fedgiac fedgiac left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea but we should internally discuss its content because of liability.

Note also that I don't see the security.txt file in the explorer:

Image

It suggests running a script, so maybe we need to add some extra deployment step?

Comment thread programs/settlement/src/security_txt.rs
Comment on lines +5 to +6
/// Copied from `solana-security-txt` v1.1.3 (dual-licensed MIT/Apache-2.0),
/// with the `link_section` gate corrected below. The upstream crate is a single

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is a bit different. Also I don't really get what has been corrected in link_section.

Comment on lines +27 to +31
// - `source_revision` / `source_release`, which upstream suggests populating
// from the build environment. Doing so would make the binary depend on
// environment variables and break the byte-for-byte reproducibility that
// `just build-verified` establishes. `solana-verify` already pins the
// deployed binary to a commit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect this is only true if we hardcode the release/revision, not in general for envs.
For the release, I expect env!("CARGO_PKG_VERSION") to work here because it should be available.
The revision is harder because there's no env for that AFAIK. We can work around it (build.rs) but I don't think it's worth it since we have reproducible builds.

Anyway, the comment doesn't say the most important thing: we don't need the commit because we have the exact code thanks to reproducibility.

Comment on lines +40 to +45
// Also required. Takes a link or free text; free text lets the one field
// every parser surfaces carry the warning that this isn't production
// software, which the standard has no dedicated field for.
policy: "TESTING ONLY: this program is an unaudited work in progress, \
deployed for testing purposes only. Do not approve this contract \
to spend more funds than you can expect to lose.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you can see the text in the explorer.
What about also creating a SECURITY.txt with this text? Later we can replace the text here with a link to that file once we're actually finalizing the code.

}

#[test]
fn program_binary_contains_security_txt() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test!

};
}

// Deliberately omitted:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could move this block after the // Optional fields. block, it reads nicely and consistently then.

@kaze-cow

Copy link
Copy Markdown
Contributor Author

will reopen when/if its necessary, as this ticket has been postponed.

@kaze-cow kaze-cow closed this Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants