Tools related to RFC 9116 (/.well-known/security.txt
). I am
optimistically using the plural, even though only one tool has been released.
This command line tool (Bash script) helps building RFC 9116 compliant, valid & well formatted security.txt files as well as automating the PGP signing & expire date updating process.
securitytxt-signer.sh input.txt [0xPGPKEY [output.txt]]
The script removes any lines not matching the specification: only valid fields,
blank lines and comments are allowed. HTTPS URLs are fetched with curl
and
non-working links are removed. Validation fails if valid mandatory fields are
missing.
The Expires
field is updated to be 364 days in future (configurable) unless
the (optional) PGP key used for signing expires earlier; in that case the key
expiration date is used instead. The script also warns if the Encryption
fields are referensing a different key than the one used for signing.
The script can also be used to re-sign a security.txt file with an updated
Expires
field as the validation removes the current signature.
- GNU Bash >= 4.0.
curl
for HTTPS URL validation.gpg
(GnuPG) for signing the security.txt.- Standard commands
sed
,awk
&grep
. date
: Compatible with both GNU coreutils & BSDdate
.
The script removes lines it does not support, but informs the user why the line was removed. The errors and warnings should be read and the invalid lines should be corrected before signing the results. Here are explanation on why the script makes these decions. It is rather strict on purpose.
- Only allow empty lines, comment lines (beginning with
#
) and lines with fields from 2.5 Field Definitions & IANA "security.txt Fields" registry. Remove everything else; including current PGP signatures. Contact
field supportsmailto:
,tel:
andhttps:
URI schemes. While other URI schemes are allowed, supporting everything is not feasible. Therefore, the script support the URI schemes present in the examples.- If the mandatory
Contact
field is missing after the validation has removed invalid contents, the script will fail. - Email addresses without the
mailto:
URI scheme will be removed. mailto:
URI supports email addresses with[[:alnum:]._%+-]+
local-parts and[[:alnum:].-]+\.[[:alpha:].]{2,4}
domains.https:
URLs are fetched. The content is not inspected, but the site must answer without any HTTP errors. HTTP codes200
and HTTP redirects are considered as valid responses; a redirect will give a warning.tel:
URIs (RFC 3966) must consist of numbers and-
separators. A+
for the country code is allowed at the beginning of the number. A common mistake is to use space as a separator, which is not allowed in RFC 3966, 5.1.1; space in the middle of the number are automatically replaced with-
. Local numbers (RFC 3966, 5.1.5) using the;phone-context=
syntax are not supported; please use global numbers.
- If the mandatory
Expires
is the other mandatory field. If the field is present it will be updated to either to be (configurable)DAYS_MAX="364"
days in future or to the expiration date of the key used for PGP signing; which comes first. If the field is missing it will be added at the end of the security.txt file.- Fields
Acknowledgments
,Canonical
,Hiring
&Policy
are expected to behttps:
URLs are validated the same way HTTPs URLs inContact
. Encryption
field supportshttps:
,openpgp4fpr:
anddns:
URI schemes.https:
URLs are validated the same way HTTPs URLs inContact
, but the key is also fetched and its fingerprint is compared with the key used for PGP signing. If the fingerprints do not match it gives a warning.openpgp4fpr:
URIs must be exactly 40 hexadecimal characters or they will be removed. The fingerprint is compared to the fingerprint of the key used for PGP signing. If the fingerprints do not match it gives a warning.dns:
URIs must referenceOPENPGPKEY
records (RFC 7929): exactly 40 hexadecimal characters followed by._openpgpkey.
. The existence and the contents of this records are not currently tested. E.g.,dns:50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccac._openpgpkey.example.com?type=OPENPGPKEY
Preferred-Languages
must not appear more than once. The first valid field seen is used and the rest are removed. Valid field consists of comma separated list of language tags (RFC 5646), recognized as one to eighta-z
characters with a possible subtag:[a-z]{1,8}(-[a-z]{1,8})?
.
- Multiple consecutive blank lines are replaced with one.
- If the input file is missing a line break at EOF it will be added.
- For operational reasons,
CRLF
line breaks are replaced withLF
line breaks. This is not required by the specification; RFC 9116, 2.2 allows both.- The ABNF Grammar (RFC 9116, 4) suggests only CRLF would be allowed
elsewhere whereas LF is an option in
cleartext
&eol
. For consistency, theCRLF
should either be mandatory or optional on the entire file, and onlyCRLF
orLF
should be used in a single file instead of mixing them. - Using
LF
is not an issue in the context of RFC 4880 that canonicalizes the signed text documents by convertingLF
toCRLF
before signing (RFC 4880, 5.4.2), and the receiving software should convert them to native line endings (RFC 4880, 5.9). - The section 4 references MIME (RFC 2046, 4.1.1) &
Net-Unicode
(RFC 5198, 2) that have chosen theCRLF
sequence as a MUST. As the intention of section 2.2 is to treat line separators more liberally, I have reported Errata ID 7743 to address this by locally redefiningCRLF
as[CR] LF
in the ABNF Grammar.
- The ABNF Grammar (RFC 9116, 4) suggests only CRLF would be allowed
elsewhere whereas LF is an option in