security.txt for Solana Contracts

Overview

security.txt

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 https://securitytxt.org/.

See the an example in the Solana Explorer: https://explorer.solana.com/address/HPxKXnBN4vJ8RjpdqDCU7gvNQHeeyGnSviYTJ4fBrDt4/security?cluster=devnet

Motivation

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.

Usage

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/example_contract.so

Example

security_txt! {
    // Required fields
    name: "Example",
    project_url: "http://example.com",
    contacts: "email:[email protected],link:https://example.com/security,discord:example#1234",
    policy: "https://github.com/solana-labs/solana/blob/master/SECURITY.md",

    // Optional Fields
    preferred_languages: "en,de",
    source_code: "https://github.com/example/example",
    encryption: "
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: Alice's OpenPGP certificate
Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html

mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
=iIGO
-----END PGP PUBLIC KEY BLOCK-----
",
    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 SECURITY.md. 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):

Format

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 protected] 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_export]
macro_rules! security_txt {
    ($($name:ident: $value:expr),*) => {
        #[cfg_attr(target_arch = "bpf", link_section = ".security.txt")]
        #[allow(dead_code)]
        #[no_mangle]
        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 [email protected].

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.

License

Licensed under either of

at your option.

Contribution

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.

Comments
  • Reducing the security.txt size by using a serialisation protocol instead and Improvement Suggestions

    Reducing the security.txt size by using a serialisation protocol instead and Improvement Suggestions

    Currently, the .security.txt takes away quite some bytes to store the information, since everything originially is in string format.

    What could be done to further improve this is using a serialisation protocol, preferably borsch, to serialise the entire security.txt key:value pairs.

    • Each pre-defined key is an unsigned 1-byte integer, giving use upto 255 keys to use. e.g., name - 0x01, project_url - 0x02, etc.

    • Now, to identify the HEADER and FOOTER we use a 6 byte magic number to indentify the same.

      HEADER = 0xDEC1A551F1ED (hex-word play on Declassified) FOOTER = 0xEDF151A5C1DE (little-endian byte swap (HEADER))

      HEADER + serialised security.txt + FOOTER

    • For the encryption key part, having PGP makes total sense to communicate securely with the contract dev. Just not sure about an external link so much. Finality of the pgp public key as a string with the recently deployed code makes more sense. Default recommendation to the dev can be to provide the PGP public key!

    Note: For any upgradeable smart contract on Solana the change in the spec of security.txt doesn't effect the eBPF bytecode exec, or anything for the smart contract devs.

    Although a minimum coordination may be requied with the Explorer services that are using this.

    Would love to hear you thoughts on this @CherryWorm!

    opened by mryalamanchi 6
  • LLVM ERROR: Global variable 'security_txt' has an invalid section specifier '.security.txt'

    LLVM ERROR: Global variable 'security_txt' has an invalid section specifier '.security.txt'

    After adding a security_txt! in my src/lib.rs, cargo build and cargo test begin to fail with this error:

    LLVM ERROR: Global variable 'security_txt' has an invalid section specifier '.security.txt': mach-o section specifier requires a segment and section separated by a comma.

    cargo +bpf build --target bpfel-unknown-unknown --release (which is being called by anchor build) does seem to work without issues even with the macro left in though

    Copying the macro directly into the code and removing the #[link_section] line also works fine

    #[macro_export]
    macro_rules! security_txt {
        ($($name:ident: $value:expr),*) => {
            #[allow(dead_code)]
            #[no_mangle]
            // #[link_section = ".security.txt"] // removing this works
            pub static security_txt: &str = concat! {
                "=======BEGIN SECURITY.TXT V1=======\0",
                 $(stringify!($name), "\0", $value, "\0",)*
                "=======END SECURITY.TXT V1=======\0"
            };
        };
    }
    
    opened by jonorally 6
  • rust-lld: error: duplicate symbol: security_txt

    rust-lld: error: duplicate symbol: security_txt

    When compiling multiple Anchor programs from the same workspace, we get this error.

    error: linking with `rust-lld` failed: exit status: 1
    
    # omitted
    
      = note: rust-lld: error: duplicate symbol: security_txt
    

    Directory structure:

    programs/
    ├── program-1
    │   ├── Cargo.toml      # solana-security-txt = "1.0.1"
    │   └── src
    ├── program-2
    │   ├── Cargo.toml      # solana-security-txt = "1.0.1"
    │   └── src
    └── program-3
        ├── Cargo.toml      # solana-security-txt = "1.0.1"
        └── src
    

    When we set the dependency in only 1 program we do not get the error.

    Note; the error occurs when we use the crate and try the utilize the macro, like so

    use solana_security_txt::security_txt;
    
    security_txt! {
    // omitted
    }
    

    EDIT

    Upon further checking, it seems other programs inherit the security txt setting when they have dependency with a program that already has a security-txt

    In below example, program-2 inherits the security-txt settings from program-1 and cannot set it's own. Also block explorers show the wrong entry.

    programs/
    ├── program-1
    │   ├── Cargo.toml      # solana-security-txt = "1.0.1"
    │   └── src
    └── program-2
        ├── Cargo.toml      # program-1 = { path = "../program-1", features = ["cpi"] }
        └── src
    

    Are we doing something wrong, or is this unintended behaviour?

    We would like to have a unique security report for each of our programs and have them depend on each other for CPI purposes.

    Thanks in advance!

    opened by sjoerd-dijkstra 4
  • document correct usage for library authors

    document correct usage for library authors

    This addresses #11:

    When using another smart-contract as dependency it also generates it's security.txt. The compiler is helpful here and prevents two conflicting security.txt being present.

    Dependencies have to omit emitting the security.txt. Solana contracts already use the no-entrypoint feature to avoid including entrypoints of dependent smart-contracts, this can easily be adapted here.

    We have brainstormed a bit, but there doesn't seem to be a fool-proof solution for solving this automatically. So there isn't much we can do about that from the perspective from this crate. The decision to include or not include the macro always has to happen from the caller, and we cannot introspect if the parent is compiled with no-entrypoint.

    This aspect is currently lacking from the documentation, working on a pull-request to fix this, and make it very clear that if you expect to be included as dependency and have an exposed no_entrypoint feature, you have to put the security.txt under that as well:

    #[cfg(not(feature = "no-entrypoint"))]
    security_txt! {
    ...
    }
    

    Unfortunately, this issue means contracts that currently do not do this cannot be used as a dependency until they are updated.

    opened by w4rum 2
  • Discussion moved to https://github.com/yarnpkg/rfcs/pull/37

    Discussion moved to https://github.com/yarnpkg/rfcs/pull/37

    Discussion moved to https://github.com/yarnpkg/rfcs/pull/37

    Originally posted by @CrabDude in https://github.com/yarnpkg/yarn/issues/2241#issuecomment-271366221

    opened by Jemerald83 1
  • Agreed. Should be fairly simple to do. Out of interest, are you aware of any larger contracts except for Pyth that are written in C?

    Agreed. Should be fairly simple to do. Out of interest, are you aware of any larger contracts except for Pyth that are written in C?

    Agreed. Should be fairly simple to do. Out of interest, are you aware of any larger contracts except for Pyth that are written in C? It seems of the currently ~2.5k deployed contracts, only 64 are written in C. (found via ELF contains llvm-project.git)

    Originally posted by @tlambertz in https://github.com/neodyme-labs/solana-security-txt/issues/1#issuecomment-1083231546

    opened by Jemerald83 0
  • Add new

    Add new "forked-from-repo" field

    We could add a new optional "forked-from-repo" field to easily indicate when a project is based on another.

    In case a bug is found, this field would allow to easily find related projects, which might have similar security issues.

    opened by tlambertz 1
Releases(v1.0.1)
Owner
Neodyme
Neodyme is a small team of security researchers, with experts in various technologies and ecosystems.
Neodyme
evm2near compiles Solidity contracts into NEAR WebAssembly contracts.

EVM → NEAR evm2near is a project for compiling EVM bytecode into wasm bytecode, with the particular goal of having that wasm artifact be executable on

Aurora 125 Dec 3, 2022
Ticketed Discreet Log Contracts (DLCs) to enable instant buy-in for wager-like contracts on Bitcoin.

dlctix Ticketed Discreet Log Contracts (DLCs) to enable instant buy-in for wager-like contracts on Bitcoin. This project is part of the Backdrop Build

null 7 Feb 29, 2024
A framework for creating PoC's for Solana Smart Contracts in a painless and intuitive way

Solana PoC Framework DISCLAIMER: any illegal usage of this framework is heavily discouraged. Most projects on Solana offer a more than generous bug bo

Neodyme 165 Dec 18, 2022
A suite of programs for Solana key management and security.

?? goki Goki is a suite of programs for Solana key management and security. It currently features: Goki Smart Wallet: A wallet loosely based on the Se

Goki Protocol 157 Dec 8, 2022
Galleries of NFTs using Solana and Rust for contracts

About this Package created to simplify the process of parsing NFTs on Solana. It consists of: Package basic things like fetch all NFTs for specific wa

Andrew Scott 1 Jan 28, 2022
Demonstrates Solana data account versioning used in supporting the Solana Cookbook article: Account Data Versioning

versioning-solana This repo demonstrates ONE rudimentary way to upgrade/migrate account data changes with solana program changes. What is data version

Frank V. Castellucci 6 Sep 30, 2022
My attempt at learning Solana program (smart contract) development through RareSkill's Solana course.

60-days-of-solana My attempt at learning Solana program (smart contract) development through RareSkill's Solana course. Originally, I was trying to cr

Jasper 3 Feb 25, 2024
Bindings to the macOS Security.framework

macOS/iOS Security framework for Rust Documentation Bindings to the Apple's Security.framework. Allows use of TLS and Keychain from Rust. License Lice

Kornel 172 Dec 24, 2022
Smart contracts for Ref Finance

Ref Finance Contracts This mono repo contains the source code for the smart contracts of Ref Finance on NEAR. Contracts Contract Reference Description

Ref Finance 92 Dec 7, 2022
Skyward Finance smart-contracts

Build and Init ./build.sh near dev-deploy res/skyward.was export CONTRACT_ID=skyward.testnet near call $CONTRACT_ID new --account_id=$CONTRACT_ID Regi

Skyward Finance 777 Jan 4, 2023
A Rust implementation of the Message Layer Security group messaging protocol

Molasses An extremely early implementation of the Message Layer Security group messaging protocol. This repo is based on draft 4 of the MLS protocol s

Trail of Bits 109 Dec 13, 2022
Rust client to Opensea's APIs and Ethereum smart contracts

opensea.rs Rust bindings & CLI to the Opensea API and Contracts CLI Usage Run cargo r -- --help to get the top level help menu: opensea-cli 0.1.0 Choo

Georgios Konstantopoulos 226 Dec 27, 2022
NFT & Marketplace Contracts with royalties and fungible token support. Sample React app included.

NFT Market Reference Implementation A PoC backbone for NFT Marketplaces on NEAR Protocol. Reference Changelog Changelog Progress: basic purchase of NF

NEAR App Examples 156 Apr 28, 2022
Examples and helpers to build NFT contracts on CosmWasm

CosmWasm NFTS This repo is the official repository to work on all NFT standard and examples in the CosmWasm ecosystem. cw721 and cw721-base were moved

CosmWasm 147 Jan 4, 2023
My code for the terra.academy course on CosmWasm smart contracts

CosmWasm Starter Pack This is a template to build smart contracts in Rust to run inside a Cosmos SDK module on all chains that enable it. To understan

Alex Incerti 0 Nov 7, 2021
Smart contracts powering Spectrum Protocol on Terra

Spectrum Core Contracts This monorepository contains the source code for the core smart contracts implementing Spectrum Protocol on the Terra blockcha

Spectrum Protocol 38 Dec 19, 2022
Audit Cargo.lock files for dependencies with security vulnerabilities

RustSec Crates ?? ??️ ?? The RustSec Advisory Database is a repository of security advisories filed against Rust crates published via crates.io. The a

RustSec 1.2k Dec 30, 2022
An uploader honeypot designed to look like poor website security.

HoneyUp An uploader honeypot designed to look like poor website security. Requirements Linux server NGiNX Rust toolchain (build only) Installation Bui

Chad Baxter 21 Dec 20, 2022
This is a template to build secret contracts in Rust to run in Secret Network

Secret Contracts Starter Pack This is a template to build secret contracts in Rust to run in Secret Network. To understand the framework better, pleas

Ethan Gallucci 1 Jan 8, 2022