security: prevent LND admin macaroon exposure in curl argv

This commit is contained in:
2026-08-15 23:00:59 -05:00
parent b436dbed95
commit a9ff168fd6
2 changed files with 31 additions and 1 deletions
+4 -1
View File
@@ -264,13 +264,16 @@ in {
curl = "${pkgs.curl}/bin/curl -fsS --cacert ${cfg.certPath}"; curl = "${pkgs.curl}/bin/curl -fsS --cacert ${cfg.certPath}";
restUrl = "https://${nbLib.addressWithPort cfg.restAddress cfg.restPort}/v1"; restUrl = "https://${nbLib.addressWithPort cfg.restAddress cfg.restPort}/v1";
# Setting macaroon permissions for other users needs root permissions # Setting macaroon permissions for other users needs root permissions
# The admin macaroon is passed to curl via a fd because argv is
# world-readable through /proc/<pid>/cmdline
script = nbLib.rootScript "lnd-create-macaroons" '' script = nbLib.rootScript "lnd-create-macaroons" ''
umask ug=r,o= umask ug=r,o=
${lib.concatMapStrings (macaroon: '' ${lib.concatMapStrings (macaroon: ''
echo "Create custom macaroon ${macaroon}" echo "Create custom macaroon ${macaroon}"
macaroonPath="$RUNTIME_DIRECTORY/${macaroon}.macaroon" macaroonPath="$RUNTIME_DIRECTORY/${macaroon}.macaroon"
adminMacaroonHex=$(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${networkDir}/admin.macaroon')
${curl} \ ${curl} \
-H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${networkDir}/admin.macaroon')" \ -H @<(printf 'Grpc-Metadata-macaroon: %s\n' "$adminMacaroonHex") \
-X POST \ -X POST \
-d '{"permissions":[${cfg.macaroons.${macaroon}.permissions}]}' \ -d '{"permissions":[${cfg.macaroons.${macaroon}.permissions}]}' \
${restUrl}/macaroon |\ ${restUrl}/macaroon |\
+27
View File
@@ -333,6 +333,33 @@ class TestSshPubkeyValidation(unittest.TestCase):
_validate_ssh_pubkey("ssh-ed25519") _validate_ssh_pubkey("ssh-ed25519")
# ---------------------------------------------------------------------------
# LND macaroon command-line safety
# ---------------------------------------------------------------------------
class TestLndMacaroonCommandLineSafety(unittest.TestCase):
"""The LND admin macaroon must never be exposed in curl's argv."""
@classmethod
def setUpClass(cls):
path = os.path.join(_REPO_ROOT, "modules", "bitcoin", "lnd.nix")
with open(path, encoding="utf-8") as f:
cls.lnd_module = f.read()
def test_admin_macaroon_not_interpolated_into_header_argument(self):
self.assertNotIn(
'-H "Grpc-Metadata-macaroon: $(',
self.lnd_module,
)
def test_admin_macaroon_header_is_passed_via_file_descriptor(self):
self.assertIn("adminMacaroonHex=$(", self.lnd_module)
self.assertIn(
"""-H @<(printf 'Grpc-Metadata-macaroon: %s\\n' "$adminMacaroonHex")""",
self.lnd_module,
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Auth-exempt paths # Auth-exempt paths
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------