iRule to serve security.txt file - RFC 9116

One week ago, on 27. April 2022, the IETF has published RFC 9116 describing the security.txt file. The purpose of this file is to aid in responsible disclosure, a process that allows security researchers to safely report vulnerabilities.

The file should be either placed in the document root or in the /.well-known folder of a webserver and it should contain information on the site owners vulnerability disclosure process.
Further details about formatting and the mandatory and optional information can be found here: 
https://www.rfc-editor.org/rfc/rfc9116

Without automation - adding this text file to every webserver can be time consuming, even in small environments. The below iRule can be used to serve the file from the BIG-IP.

when HTTP_REQUEST {
    if {  [string tolower [HTTP::path]] equals "/.well-known/security.txt" } {
        HTTP::respond 200 content "
            # Our security address
            Contact: mailto:security@example.com

            # Our OpenPGP key
            Encryption: https://example.com/pgp-key.txt

            # Our security policy
            Policy: https://example.com/security-policy.html

            # Our security acknowledgments page
            Acknowledgments: https://example.com/hall-of-fame.html

            Expires: 2021-12-31T18:37:07z"
    }
}

Note: The RFC mentions the process of PGP signing the security.txt file. I guess this can be done with iRulesLX, however - I didn't have time yet to figure out the details about if and how it can be done. If anyone is faster or more knowledgeable than me with iRulesLX - the stage is yours.

 

Updated Jan 14, 2023
Version 2.0

Was this article helpful?

6 Comments

  • Small error:

    if {  [string tolower [HTTP::path]] equals ".well-known/security.txt" } {

     I think it should be:

    if {  [string tolower [HTTP::path]] equals "/.well-known/security.txt" } {
  • No idea about the details of iRulesLX. But it seems way to much overhead to call something external just to serve some text.

    Signing the file with the "clearsign" option as recommended is nothing more then a plain text readable file in this case, plus the signature and PGP headers.

    All you do is the following. The --default-key option is only needed, in case you have multiple keys.

    gpg --clearsign --default-key security@example.com security.txt

     This will generate a security.txt.asc file. Then you paste that content in your iRule.

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA512
    
    # Our security address
    Contact: mailto:security@example.com
    
    # Our OpenPGP key
    Encryption: https://example.com/pgp-key.txt
    
    # Our security policy
    Policy: https://example.com/security-policy.html
    
    # Our security acknowledgments page
    Acknowledgments: https://example.com/hall-of-fame.html
    
    Expires: 2021-12-31T18:37:07z"
    
    -----BEGIN PGP SIGNATURE-----
    
    iIcEARYKAC8WIQSulmNYqOEvaLEXuXBhVhukMyqDOwUCYnZbLBEcdGhlZHVkZUBt
    YXJjby5tcwAKCRBhVhukMyqDO7BKAP9fRJXm7xBW8DgvBurYlQtkl0ROc23gONpf
    eeZupn3JxAD/YXNnZaC33dcHh7c7W22QK673XFtY7DmKpT7wUXCtlQs=
    =3hMe
    -----END PGP SIGNATURE-----

    I heard F5 is also bit in the nginx business. 🙂
    The open source enthusiasts will love to serve simple static content directly from the configuration. Here is a quick example.

    Create a simple nginx config file like security.txt.conf with the following content.

    server {
        server_name localhost;
        listen 80;
    
        location / {
            types {}
            default_type text/html;
    
            return 200 '
            <html><body><br>
            -----BEGIN PGP SIGNED MESSAGE-----<br>
            Hash: SHA512<br>
            <br>
            # Our security address<br>
            Contact: mailto:security@example.com<br>
            <br>
            # Our OpenPGP key<br>
            Encryption: https://example.com/pgp-key.txt<br>
            <br>
            # Our security policy<br>
            Policy: https://example.com/security-policy.html<br>
            <br>
            # Our security acknowledgments page<br>
            Acknowledgments: https://example.com/hall-of-fame.html<br>
            <br>
            Expires: 2021-12-31T18:37:07z"<br>
            <br>
            -----BEGIN PGP SIGNATURE-----<br>
            <br>
            iIcEARYKAC8WIQSulmNYqOEvaLEXuXBhVhukMyqDOwUCYnZbLBEcdGhlZHVkZUBt<br>
            YXJjby5tcwAKCRBhVhukMyqDO7BKAP9fRJXm7xBW8DgvBurYlQtkl0ROc23gONpf<br>
            eeZupn3JxAD/YXNnZaC33dcHh7c7W22QK673XFtY7DmKpT7wUXCtlQs=<br>
            =3hMe<br>
            -----END PGP SIGNATURE-----<br>
            </body></html>
            ';
        }
    }

    Now lets fire up a container to see what we get.

    docker run -it --rm --name nginxsecuritytxt -p 8080:80 -v $PWD/security.txt.conf:/etc/nginx/conf.d/default.conf nginx

    Lets browse the page in the terminal.

    lynx -collapse_br_tags=0 -trim_blank_lines=0 -nomargins=1 -dump http://localhost:8080/

    You should see something like this.

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA512
    
    # Our security address
    Contact: mailto:security@example.com
    
    # Our OpenPGP key
    Encryption: https://example.com/pgp-key.txt
    
    # Our security policy
    Policy: https://example.com/security-policy.html
    
    # Our security acknowledgments page
    Acknowledgments: https://example.com/hall-of-fame.html
    
    Expires: 2021-12-31T18:37:07z"
    
    -----BEGIN PGP SIGNATURE-----
    
    iIcEARYKAC8WIQSulmNYqOEvaLEXuXBhVhukMyqDOwUCYnZbLBEcdGhlZHVkZUBt
    YXJjby5tcwAKCRBhVhukMyqDO7BKAP9fRJXm7xBW8DgvBurYlQtkl0ROc23gONpf
    eeZupn3JxAD/YXNnZaC33dcHh7c7W22QK673XFtY7DmKpT7wUXCtlQs=
    =3hMe
    -----END PGP SIGNATURE-----

     

  • Hi ElDuderino,

    probably you are right. To serve the site with the help of iRulesLX is pretty over-engineered and also too expensive on the CPU. I had it in mind for a situation when you want to serve the file for multiple domains with different PGP signatures per each domain. However... maybe even in such case a static solution would perform better.

    AWESOME that you provided a solution for NGINX.

    KR
    Daniel

  • could create an ifile for each, signing them as mentioned by ElDuderino before uploading, then switching based on host. ifiles can be automated with icontrol rest, so that could be a cron job or a web hook.