legacy-sftp

An n8n community SFTP node with opt-in legacy ssh-rsa host-key and user-authentication support.

Package Information

Released: 2 mo ago
Downloads: 0 weekly / 0 monthly
Latest Version: 0.1.3

Documentation

n8n-nodes-legacy-sftp

n8n-nodes-legacy-sftp is a standalone n8n community node for SFTP endpoints that require legacy RSA/SHA-1 SSH compatibility. It is designed for services with the same client requirements observed on Gamma Telecom SFTP:

HostKeyAlgorithms=+ssh-rsa
PubkeyAcceptedAlgorithms=+ssh-rsa

The package does not modify, patch, copy, or fork n8n's built-in FTP/SFTP node. The built-in node was used only as a reference for node UX, credential testing, binary handling, per-item execution, error handling, and connection cleanup.

Status

Version 0.1.0 provides:

  • List files and directories
  • Download a remote file to an n8n binary field
  • private-key authentication with an optional passphrase
  • strict SHA256 host-key verification, enabled by default
  • modern SSH behavior by default
  • explicit opt-in ssh-rsa compatibility for the server host key
  • explicit opt-in RSA/SHA-1 ssh-rsa compatibility for public-key user authentication
  • normal encrypted n8n credential storage
  • Continue On Fail behavior and paired-item output
  • a credential connection test
  • unit tests, a live-endpoint test, and a containerized legacy OpenSSH fixture

Upload, rename, delete, and other SFTP operations are intentionally outside the version 1 scope.

Security warning

In this context, ssh-rsa means an RSA signature using SHA-1. SHA-1 signatures are deprecated. Legacy behavior is disabled by default and should be enabled only for a known endpoint that cannot yet be upgraded.

The node never enables ssh-dss/DSA.

Keep Strict Host Key Checking enabled in production. Confirm host-key fingerprints through a trusted provider channel rather than trusting a value discovered from the same network path used for the connection.

Why ssh2

The node uses ssh2 1.17.0 directly rather than a higher-level SFTP wrapper. Direct access is required because Gamma compatibility involves two independent SSH decisions:

  1. ConnectConfig.algorithms.serverHostKey controls the server host-key algorithm.
  2. The parsed RSA authentication key and ssh2 authentication selection control the signature algorithm used for public-key user authentication.

Accepting an ssh-rsa host key alone does not solve send_pubkey_test: no mutual signature algorithm. The user-authentication request must also be signed with the legacy ssh-rsa RSA/SHA-1 algorithm when the endpoint accepts no RSA/SHA-2 signature.

ssh2 supports both paths. For RSA public-key authentication it uses the server's server-sig-algs information when available, prefers RSA/SHA-2, and can fall back to the ssh-rsa key/signature algorithm with SHA-1. The parsed key's sign(data, hashAlgorithm) implementation receives the selected hash.

This package adds an explicit policy around that behavior:

Credential state Server host-key policy RSA user-authentication policy
Legacy compatibility disabled Remove ssh-rsa and ssh-dss Reject SHA-1; allow RSA/SHA-2
Legacy mode: Host Key Only Append ssh-rsa; remove ssh-dss Reject SHA-1; require RSA/SHA-2
Legacy mode: Host Key + User Authentication Append ssh-rsa; remove ssh-dss Allow ssh2 to negotiate the ssh-rsa/SHA-1 fallback

The implementation uses only public ssh2 APIs: Client, ConnectConfig.algorithms, authHandler, utils.parseKey(), ParsedKey.sign(), hostVerifier, and the SFTP wrapper. It does not patch ssh2 or reach into private module internals.

See docs/ssh-library-research.md for the source-level analysis and alternatives considered.

Compatibility

Endpoint Configuration
Modern OpenSSH or another modern RFC-compliant SFTP server Leave legacy compatibility disabled
Modern server using an RSA user key Leave legacy compatibility disabled; RSA/SHA-2 remains available
Server offering only an ssh-rsa host key but accepting RSA/SHA-2 user authentication Enable legacy compatibility and select Host Key Only
Gamma-style endpoint requiring ssh-rsa for both host key and user authentication Enable legacy compatibility and select Host Key + User Authentication (Gamma Compatible)
DSA-only endpoint Not supported intentionally

A live Gamma account was not available in the build environment. The repository includes a controlled OpenSSH fixture configured with both HostKeyAlgorithms ssh-rsa and PubkeyAcceptedAlgorithms ssh-rsa, plus an environment-driven live test for Gamma or another provider endpoint. A release should not claim provider certification without executing the external test against that provider.

Credential

Create a credential of type Legacy SFTP Credential.

Field Required Description
Host Yes SFTP hostname or IP address
Port Yes SSH port, default 22
Username Yes SFTP account username
Private Key Yes OpenSSH, PEM, or PuTTY PPK private key
Passphrase No Passphrase for an encrypted private key
Strict Host Key Checking Yes Reject an untrusted server key; default true
Trusted Host Key Fingerprints When strict checking is enabled One or more OpenSSH SHA256 host-key fingerprints
Enable Legacy RSA Compatibility Yes Opt-in legacy switch; default false
Legacy RSA Mode When legacy compatibility is enabled Host Key Only or Host Key + User Authentication (Gamma Compatible)

Private keys, passphrases, host-key fingerprints, and other credential values are stored through n8n's normal encrypted credential system. The Docker example requires an explicit N8N_ENCRYPTION_KEY so stored credentials remain decryptable across container replacement.

Obtain and verify a host-key fingerprint

Use a fingerprint supplied by the SFTP provider whenever possible. To inspect the RSA host key visible from the network:

ssh-keyscan -p 22 -t rsa sftp.example.com 2>/dev/null \
  | ssh-keygen -lf - -E sha256

Copy only the SHA256:... value into Trusted Host Key Fingerprints after comparing it with a provider-published or independently confirmed value. Discovery with ssh-keyscan does not itself establish trust.

Multiple fingerprints can be separated by spaces, commas, semicolons, or new lines. This supports controlled host-key rotation without disabling verification.

Gamma-style credential settings

Strict Host Key Checking: true
Trusted Host Key Fingerprints: SHA256:<provider-confirmed-value>
Enable Legacy RSA Compatibility: true
Legacy RSA Mode: Host Key + User Authentication (Gamma Compatible)

Use an RSA private key for a Gamma-style endpoint that accepts only the ssh-rsa public-key algorithm. Enabling legacy mode cannot make an Ed25519 or ECDSA user key satisfy an RSA-only authentication policy.

Operations

List

Lists a remote directory. Recursive traversal is optional, uses a configurable maximum depth from 1 to 100, and does not follow symbolic links.

Each remote entry becomes one n8n item:

{
  "type": "-",
  "name": "report.csv",
  "path": "/outbound/report.csv",
  "size": 12345,
  "accessTime": "2026-07-23T10:00:00.000Z",
  "modifyTime": "2026-07-23T10:01:00.000Z",
  "mode": "0640",
  "rights": {
    "user": "rw-",
    "group": "r--",
    "other": "---"
  },
  "owner": 1000,
  "group": 1000,
  "longname": "-rw-r----- ... report.csv"
}

Download

Streams a remote file through n8n's binary-data helper. The default output field is data. Existing JSON and binary data on the input item are preserved.

Community Nodes installation

This package is intended for self-hosted n8n. It has a runtime dependency on ssh2, so under current n8n verification rules it is an installable unverified community node rather than an n8n Cloud verified node.

Install through the n8n user interface

After the package is published to npm:

  1. Open Settings > Community Nodes.
  2. Select Install.
  3. Enter n8n-nodes-legacy-sftp.
  4. Review and accept the community-node risk notice.
  5. Install the package.
  6. Restart n8n only if the node does not appear after installation.

The instance owner or another administrator with community-node installation permission must perform this operation.

Manual installation

Run the following as the operating-system user that runs n8n:

mkdir -p ~/.n8n/nodes
cd ~/.n8n/nodes
npm install n8n-nodes-legacy-sftp

Restart every n8n process that loads nodes. In queue mode, install the same package version on the main process and every worker.

For a locally built package before npm publication:

npm install --omit=optional
npm run build
npm pack

mkdir -p ~/.n8n/nodes
cd ~/.n8n/nodes
npm install /absolute/path/to/n8n-nodes-legacy-sftp-0.1.0.tgz

Install into an existing Docker container

For a container named n8n:

docker exec -u node n8n sh -lc \
  'mkdir -p /home/node/.n8n/nodes && cd /home/node/.n8n/nodes && npm install n8n-nodes-legacy-sftp'

docker restart n8n

Persist /home/node/.n8n; otherwise the installed package and n8n encryption key can be lost when the container is replaced.

Build a custom n8n image

The repository includes a multi-stage Dockerfile and Compose example:

cp docker/.env.example docker/.env
openssl rand -hex 32
# Put the generated value in N8N_ENCRYPTION_KEY inside docker/.env.

docker compose --env-file docker/.env -f docker/docker-compose.yml build
docker compose --env-file docker/.env -f docker/docker-compose.yml up -d

docker/.env.example intentionally leaves N8N_ENCRYPTION_KEY empty. Compose refuses to start until a value is supplied. Review and pin N8N_VERSION before deployment.

The builder installs dependencies, runs the current n8n node build, packs the community node, and installs the resulting tarball into the official n8n image. Optional native ssh2 acceleration is omitted; ssh2 uses its portable JavaScript implementation.

Example workflow

Import examples/list-and-download.workflow.json. Select a Legacy SFTP Credential on both imported nodes and replace the example remote paths.

Project structure

See PROJECT_TREE.md for the complete source tree and the responsibility of each directory.

Development

Requirements:

  • Node.js 22 or later
  • npm 10 or later

Install and validate:

npm install --omit=optional
npm run lint
npm run typecheck
npm test
npm audit --omit=dev
npm pack --dry-run

Start a development n8n instance with hot reload:

npm run dev

Build the distributable package:

npm run build
npm pack

Integration tests

Controlled legacy OpenSSH fixture

The deterministic Docker fixture permits only:

HostKeyAlgorithms ssh-rsa
PubkeyAcceptedAlgorithms ssh-rsa

Run:

npm install --omit=optional
npm run test:legacy-container

The test performs three independent attempts:

  1. Modern mode must fail because the server offers only an ssh-rsa host key.
  2. Host Key Only must pass host-key negotiation but fail because RSA/SHA-1 user-authentication signatures remain blocked.
  3. Host Key + User Authentication must connect, report ssh-rsa as the negotiated server host-key algorithm, authenticate with an RSA/SHA-1 ssh-rsa signature, and list a directory.

The third attempt can succeed only when both Gamma compatibility paths are active.

Live provider endpoint

The live test is skipped unless its required environment variables are set:

export LEGACY_SFTP_TEST_HOST=sftp.example.com
export LEGACY_SFTP_TEST_PORT=22
export LEGACY_SFTP_TEST_USERNAME=account-name
export LEGACY_SFTP_TEST_PRIVATE_KEY_FILE="$HOME/.ssh/id_rsa"
export LEGACY_SFTP_TEST_HOST_KEY_FINGERPRINTS='SHA256:confirmedFingerprint'
export LEGACY_SFTP_TEST_ENABLE_LEGACY_RSA=true
export LEGACY_SFTP_TEST_LEGACY_RSA_MODE=hostKeyAndUserAuth
export LEGACY_SFTP_TEST_PATH=/

npm run test:integration

Set LEGACY_SFTP_TEST_STRICT_HOST_KEY=false only in an isolated disposable test environment. Do not use it for production validation.

Publishing

The package follows the current programmatic community-node layout and uses @n8n/node-cli for build, lint, development, prerelease validation, and release handling.

The supplied workflows perform the following:

  • .github/workflows/ci.yml audits runtime dependencies, lints, type-checks, builds, runs unit tests, runs the three-stage legacy OpenSSH fixture, and performs an npm pack dry run.
  • .github/workflows/publish.yml verifies the version tag, injects exact repository metadata from GITHUB_REPOSITORY, repeats the validation and compatibility gates, and publishes from GitHub Actions with npm provenance.
  • The source package does not invent a GitHub owner. Repository, homepage, and issue-tracker metadata are derived from the repository that actually executes the workflow.

Release sequence:

  1. Push the project to a public GitHub repository.
  2. Run the clean-checkout release gates in VALIDATION.md.
  3. For an existing npm package, configure npm Trusted Publishing for that repository and .github/workflows/publish.yml.
  4. For an initial npm publication, add a package-scoped granular npm token as the NPM_TOKEN repository secret. After the first publication, configure Trusted Publishing and remove the token.
  5. Run npm run release locally. The current n8n CLI updates the version, changelog, commit, tag, GitHub release, and pushes; it does not publish locally by default.
  6. The version tag triggers the publish workflow. The tag must match package.json, with or without a leading v.

The publish job grants only contents: read and id-token: write. It supports token-based bootstrap authentication when NPM_TOKEN exists and otherwise relies on npm Trusted Publishing/OIDC.

n8n Cloud and verified-node limitation

The package necessarily has the runtime dependency ssh2. Current n8n verified-node rules do not permit runtime dependencies, so this package is intended for self-hosted n8n as an unverified community node. The project sets n8n.strict to false, uses the official configWithoutCloudSupport ESLint profile, and disables only the no-runtime-dependencies rule for package.json. All other community-node, credential, node, import-resolution, and TypeScript lint checks remain active.

Troubleshooting

no matching host key type found or no matching host key format

Enable Legacy RSA Compatibility. The node enables ssh-rsa only and continues to reject ssh-dss/DSA.

send_pubkey_test: no mutual signature algorithm

Select Host Key + User Authentication (Gamma Compatible). Host Key Only changes only server host-key negotiation and deliberately blocks the RSA/SHA-1 user-authentication signature.

Host key verification failed

Verify the presented SHA256 fingerprint through a trusted channel. Do not copy an unverified value into the credential simply to make the connection succeed.

All configured authentication methods failed

Check the username, private key, passphrase, server-side authorized key, and selected legacy mode. Version 1 uses private-key authentication only.

Encrypted key cannot be parsed

Confirm that the passphrase is correct and that the key is in an OpenSSH, PEM, or PuTTY PPK format supported by ssh2.

Gamma-compatible mode still fails under FIPS policy

Full Gamma mode requires an RSA/SHA-1 signature. A Node.js/OpenSSL runtime configured to prohibit SHA-1 signatures can reject the operation. Use an approved isolated runtime for the legacy endpoint or require the provider to upgrade the SSH service.

Dependency security status

The package pins ssh2 1.17.0, the latest published npm release used for this implementation. NVD lists CVE-2025-70034 against that version. The corresponding GitHub advisory is currently unreviewed, provides no npm package mapping or affected/fixed range, and publishes no actionable reproducer or code location; upstream reports that no technical details were supplied.

This is recorded as an unresolved supply-chain risk rather than dismissed. Runtime dependencies are audited in CI, ssh2 is pinned exactly, and SECURITY.md requires reassessment before every release.

Validation

See VALIDATION.md for completed checks, environment limitations, and mandatory release gates.

License

MIT

Discussion