solana-security-txt 1.0.1

security-txt is a macro that helps security researchers contact you about vulnerabilities in your smart contract


This library defines a macro, which allows developers to provide easy-to-parse information to security researchers that wish to contact the authors of a Solana smart contract. It is inspired by

See the an example in the Solana Explorer:


Users typically interact with a Solana smart contract via the project's web interface, which knows the contract's address. Security researchers often don't.

Especially for smaller or private projects, identification from just the contract's address is hard and time-consuming, if not impossible. This slows down or prevents bug reports from reaching the developers.

Having standardized information about your project inside your contract makes it easy for whitehat researchers to reach you if they find any problems.

To maximize compatibility with existing deployment setups, multisigs and DAOs, this security.txt is implemented to simply be a part of your program rather than an external contract.


Add the following to the [dependencies] section of your Cargo.toml:

solana-security-txt = "1.0.1"

To install the querying tool, execute

cargo install query-security-txt

In general, there are two ways to specify the information. Either directly inside the contract to store it on-chain or by linking to a web page. The former has the advantage that it is easy to set up, but has the drawback that any changes require a program upgrade. Program upgrades shouldn't be done lightly.

Therefore, it is recommended to have all information you expect to change on a website, which you can then link to inside the security.txt.

As many projects are best reachable via Telegram or Discord there is native support for these contact methods. But be aware that handles might change, for example, if you change your Discord username.

The security_txt macro is intentionally kept brief. As such, it doesn't do any input validation. For optimal experience, please verify the format before uploading the contract to the chain. This can be done with the provided query-security-txt program, which can not only be called with on-chain contracts but also local binaries:

query-security-txt target/bpfel-unknown-unknown/release/


security_txt! {
// Required fields
name: "Example",
project_url: "",
contacts: ",link:,discord:example#1234",
policy: "",

// Optional Fields
preferred_languages: "en,de",
source_code: "",
encryption: "
Comment: Alice's OpenPGP certificate

auditors: "None",
acknowledgements: "
The following hackers could've stolen all our money but didn't:
- Neodyme

Example Policies

Bug bounty policies can be a bit daunting to write. For a good and thorough example, take a look at Solana Foundation's But even a very brief policy is better than none. A starting point might be something like:

We pay a bug bounty at our discretion after verifying the bug, up to 10% of value at risk, limited by a maximum of $x. This bounty is only paid out if details about the security issues have not been provided to third parties before a fix has been introduced and verified. Furthermore, the reporter is in no way allowed to exploit the issue without our explicit consent.

If you don't pay bounties, which might be sensible for toy projects that don't handle much value, you can also put something like

We do not pay a bug bounty.

For more inspiration, take a look at how other large Solana projects structure their policies (random, non-exhaustive collection):


This crate uses a macro to construct one long security.txt string. It begins with the start marker =======BEGIN SECURITY.TXT V1=======\0, and ends with the end marker =======END SECURITY.TXT V1=======\0. In between is a list of strings, delimited by nullbytes. Every pair of two strings forms a key-value pair.

All values need to be string literals that may not contain nullbytes. The contract should not include the security.txt markers anywhere else, otherwise naive parsers might fail.

The following fields are supported, some of which are required for this to be considered a valid security.txt:

Field Type Description
name string (required) The name of the project. If the project isn't public, you can put private.
project_url https url (required) A URL to the project's homepage/dapp. If the project isn't public, you can put private.
contacts list (required) A comma-separated list of contact information in the format <contact type>:<contact information>. Should roughly be ordered in preference. Possible contact types are email, link, discord, telegram, twitter and other. Prefer contact types that likely won't change for a while, like a email address.
policy link/text (required) Either a link or a text document describing the project's security policy. This should describe what kind of bounties your project offers and the terms under which you offer them.
preferred_languages list (optional) A comma-separated list of preferred languages (ISO 639-1).
source_code link (optional) A URL to the project's source code.
encryption link/text (optional) A PGP public key block (or similar) or a link to one.
auditors link/list (optional) A comma-separated list of people or entities that audited this smart contract, or a link to a page where audit reports are hosted. Note that this field is self-reported by the author of the program and might not be accurate.
acknowledgements link/text (optional) Either a link or a text document containing acknowledgements to security researchers who have previously found vulnerabilities in the project.
expiry date (optional) The date the security.txt will expire. The format is YYYY-MM-DD.

Security of this Crate

To minimize dependencies, the security.txt parser is disabled by default, and will only be built if the feature parser is set.

Literally all this crate does is define a single macro:

macro_rules! security_txt {
($($name:ident: $value:expr),*) => {
#[cfg_attr(target_arch = "bpf", link_section = ".security.txt")]
pub static security_txt: &str = concat! {
"=======BEGIN SECURITY.TXT V1=======\0",
$(stringify!($name), "\0", $value, "\0",)*
"=======END SECURITY.TXT V1=======\0"

If you want, you can just copy this into your contract instead of depending on this crate.

Should you notice any errors, please don't hesitate to open an issue, or in critical cases reach us under

Additional ELF Section

In addition to inserting the security.txt string into the binary, the macro creates a new .security.txt ELF section via the #[link_section] attribute. Because of how Rust strings work, it is not easily possible to place the entire string in a separate ELF section, so this is simply a tuple of a pointer to the actual string and its length.

ELF-aware parsers can thus simply look at this section and are not required to search the haystack for the security.txt markers.

Since Solana may move away from ELF binaries in the future, this section is optional in the standard.


Licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.