Skip to content

feat: stabilize SFTP and add secure SSH terminal integration - #2694

Open
bajrangCoder wants to merge 7 commits into
mainfrom
feat/sftp-improvements
Open

feat: stabilize SFTP and add secure SSH terminal integration#2694
bajrangCoder wants to merge 7 commits into
mainfrom
feat/sftp-improvements

Conversation

@bajrangCoder

Copy link
Copy Markdown
Member

Summary

This PR improves the reliability and security of Acode's SFTP integration and adds interactive SSH terminal support using the existing Maverick Synergy SSH library.

It addresses the SFTP lifecycle, cleanup, and path issues reported in:

SFTP reliability improvements

  • Prevent overlapping SFTP connection attempts.
  • Properly close previous SFTP and SSH connections before switching servers.
  • Reduce Maverick SFTP window sizes and asynchronous request limits for Android.
  • Improve handling of disconnected and partially initialized sessions.
  • Clean up SFTP files, folders, recents, and active editor references when a storage is removed.
  • Preserve URL path boundaries when removing or comparing remote entries.
  • Improve private-key and connection error handling.

SSH terminal integration

  • Add interactive SSH terminal sessions using Maverick SessionChannelNG.
  • Allocate an xterm-256color PTY and start an interactive remote shell.
  • Stream binary terminal output safely through the Cordova bridge.
  • Support password and private-key authentication.
  • Forward terminal input in order through a per-session native writer.
  • Synchronize terminal dimensions with the remote PTY.
  • Handle exit codes, connection errors, intentional closes, and plugin lifecycle cleanup.
  • Keep terminal connections independent from the global SFTP browser connection.
  • Add “Open SSH Terminal” to saved SFTP storage and open-folder context menus.
  • Prevent remote hosts from invoking Acode's local OSC 7777 file-opening protocol.
  • Keep remote-terminal creation internal; it is not exposed through the public Acode plugin API.

Secure SFTP profiles

Previously, SFTP URLs could contain usernames, passwords, key-file paths, and passphrases.

This PR replaces persisted connection URLs with opaque identifiers:

sftp://profile-<uuid>/remote/path

The corresponding connection profile is stored natively and encrypted using:

  • Android Keystore-managed AES key
  • AES/GCM/NoPadding
  • Random IV per profile encryption
  • Profile ID as authenticated additional data

Encrypted profiles contain the server details and authentication material. Profile reads exposed to JavaScript return metadata only and never return passwords, passphrases, or private-key contents.

Private-key files selected for new profiles are read by the native plugin and stored inside the encrypted profile instead of being copied into an SFTP URL.

Migration

On startup, legacy SFTP URLs are migrated across:

  • Saved storages
  • Remembered files
  • Remembered folders
  • Recent files
  • Recent folders
  • File-browser state

Migration behavior is intentionally conservative:

  • Repeated URLs using the same credentials reuse the migrated profile.
  • Paths are preserved while credentials and query parameters are removed.
  • A failed profile migration leaves the legacy URL unchanged.
  • App-private plaintext key copies are removed only after successful migration.
  • Shared profiles are not deleted while another saved storage still references them.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 8, 2026
@bajrangCoder
bajrangCoder marked this pull request as ready for review August 8, 2026 03:27
@UnschooledGamer UnschooledGamer added the S/FTP Issues and Pull requests related to SFTP/FTP. label Aug 8, 2026
@greptile-apps

greptile-apps Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces credential-bearing SFTP URLs with encrypted native profiles, strengthens SFTP connection and cleanup handling, and adds profile-backed interactive SSH terminals.

  • Migrates persisted SFTP references to opaque profile URLs during startup.
  • Adds native encrypted profile management and SSH shell lifecycle APIs.
  • Integrates remote terminals into saved-storage and folder context menus.
  • Updates URL-boundary handling, storage removal cleanup, and sensitive prompt behavior.

Confidence Score: 5/5

The PR appears safe to merge because no eligible blocking failure remains.

No blocking failure remains.

Important Files Changed

Filename Overview
src/lib/sftpProfiles.js Introduces recursive persisted-state migration from credential-bearing URLs to encrypted native profiles, including profile reuse and post-migration key-copy cleanup.
src/plugins/sftp/src/com/foxdebug/sftp/Sftp.java Extends the Cordova plugin with profile-backed SFTP connections and independently managed interactive SSH shell sessions.
src/plugins/sftp/src/com/foxdebug/sftp/SftpSecurityStore.java Adds Android Keystore-backed AES-GCM storage for SFTP authentication profiles.
src/components/terminal/terminal.js Adds remote SSH event streaming, ordered input, PTY resizing, exit handling, and shell cleanup to the terminal component.
src/fileSystem/sftp.js Converts the filesystem backend to native profile identifiers and serializes overlapping connection attempts.
src/pages/fileBrowser/fileBrowser.js Adds SSH-terminal actions and coordinates storage removal with recent-item, folder, editor, connection, and profile cleanup.
src/main.js Runs legacy SFTP-profile migration during device-ready initialization before application and plugin loading.
src/utils/Url.js Strengthens URL ancestry comparisons so cleanup respects path-segment boundaries.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Legacy SFTP URLs in localStorage] --> B[migrateLegacySftpProfiles]
    B --> C[Native encrypted profile store]
    C --> D[Opaque sftp://profile-id/path URLs]
    D --> E[SFTP filesystem client]
    D --> F[SSH terminal creation]
    E --> G[Maverick SFTP session]
    F --> H[Maverick interactive shell]
    I[Remove saved storage] --> J[Close matching SFTP connection]
    J --> K[Delete unreferenced native profile]
Loading

Reviews (3): Last reviewed commit: "refactor(sftp): use themed secure profil..." | Re-trigger Greptile

RohitKushvaha01

This comment was marked as outdated.

Comment thread src/plugins/sftp/src/com/foxdebug/sftp/SftpSecurityStore.java
@UnschooledGamer UnschooledGamer added the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Aug 8, 2026
@github-actions github-actions Bot removed the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Aug 8, 2026
@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Preview Release for this, has been built.

Click here to view that github actions build

@bajrangCoder

This comment was marked as outdated.

Comment thread src/pages/fileBrowser/fileBrowser.js Fixed
@bajrangCoder

This comment was marked as outdated.

@RohitKushvaha01 RohitKushvaha01 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@UnschooledGamer

UnschooledGamer commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Tested with Ed25519 private key auth

SSH Terminal works completely fine on my device, find the screenshots below. Tho I cannot keep the Termux Home directory via SFTP open for too long without Error.

Screenshot_2026-08-09-22-22-48-259-edit_com.foxdebug.acode.jpg

IMG_20260809_222916.jpg

Acode Crash Report

WebView Version: 150.0.7871.181
App Language: en-IN
Error Message: Attempt to invoke virtual method 'void com.sshtools.client.sftp.SftpMessage.release()' on a null object reference
App Version: 1.12.9-pr.2694 (1005)
Device: Xiaomi M2003J15SC
Android Version: 12 (SDK 31)

Stack Trace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.sshtools.client.sftp.SftpMessage.release()' on a null object reference
at com.sshtools.client.sftp.SftpChannel.getOKRequestStatus(SftpChannel.java:694)
at com.sshtools.client.sftp.SftpHandle.close(SftpHandle.java:291)
at com.sshtools.client.sftp.SftpClient.ls(SftpClient.java:934)
at com.foxdebug.sftp.Sftp$12.run(Sftp.java:1124)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
at java.lang.Thread.run(Thread.java:1564)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request S/FTP Issues and Pull requests related to SFTP/FTP.

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

The app crashes when loading SFTP files Deleted SFTP folders still tries reconnect

4 participants