8 मिनट पढ़ें

क्या SSH environment forwarding स्थानीय संदर्भ लीक कर सकता है?

SSH environment forwarding दूरस्थ कमांड को स्थानीय संदर्भ दिखा सकता है। SendEnv और AcceptEnv जाँचें और सटीक variable सूची का परीक्षण करें।

क्या SSH environment forwarding स्थानीय संदर्भ लीक कर सकता है?

SSH environment forwarding किसी दूरस्थ काम को जितनी स्थानीय जानकारी चाहिए, उससे कहीं अधिक लीक कर सकता है। चैनल encrypted होता है, लेकिन encryption केवल रास्ते की रक्षा करता है। वह AWS_PROFILE, GIT_AUTHOR_EMAIL, किसी tenant के नाम या अंदरूनी feature flag को दूसरी मशीन पर चल रहे process के लिए उचित input नहीं बना देता।

मैं forward होने वाले हर variable को दूरस्थ command का argument मानता हूँ। इसलिए उसका नाम, कारण, जिम्मेदार व्यक्ति और test होना चाहिए। laptop पर सुविधाजनक SSH configuration से लिया गया wildcard इस कसौटी पर खरा नहीं उतरता, क्योंकि कोई नया मिलता-जुलता स्थानीय variable जुड़ते ही उसका अर्थ बदल जाता है।

सुरक्षित लक्ष्य पूरी तरह खाली दूरस्थ environment नहीं है। sshd, login account, shell और wrapper अपना base environment बनाते हैं। लक्ष्य अधिक सटीक है: client केवल लिखित contract में दर्ज workflow variables दे, server उससे बड़ा set स्वीकार न करे, और test आवश्यक values के पहुँचने तथा canary values के ठुकराए जाने, दोनों को साबित करे।

Forwarding के लिए SSH के दोनों सिरों की सहमति चाहिए

OpenSSH environment forwarding के दो gate हैं। client पर SendEnv स्थानीय process environment से नाम चुनता है, जबकि client-side SetEnv सीधे NAME=VALUE pair देता है। server पर AcceptEnv तय करता है कि client से आए कौन से नाम session environment में जाएँगे। सामान्यतः कोई नाम तभी पार होता है जब client उसे भेजे और server उसे स्वीकार करे।

RFC 4254 इस व्यवस्था के नीचे का protocol बताता है। shell या command शुरू होने से पहले client env प्रकार का SSH channel request भेज सकता है, जिसमें एक variable name और एक value होती है। RFC यह भी चेतावनी देता है कि privileged process में environment को बिना नियंत्रण के set करना खतरनाक है। वह allowlist रखने या पर्याप्त privilege हटने के बाद variables set करने की सलाह देता है। यह चेतावनी protocol specification का ही हिस्सा है।

OpenSSH manuals एक अपवाद बताते हैं जो audit में अक्सर भ्रम पैदा करता है: client जब pseudo-terminal माँगता है, तब protocol की जरूरत के कारण TERM हमेशा भेजा और स्वीकार किया जाता है। जिस automation को terminal नहीं चाहिए, उसे ssh -T के साथ चलाएँ। इससे इस रास्ते से terminal behavior, interactive startup surprises और TERM हट जाते हैं।

इस handshake से चार बातें निकलती हैं।

  • व्यापक SendEnv ऐसे server के सामने निष्क्रिय रहता है जो कुछ स्वीकार नहीं करता, लेकिन administrator के AcceptEnv बढ़ाते ही सक्रिय हो जाता है।
  • व्यापक AcceptEnv सावधान client के साथ निष्क्रिय रहता है, लेकिन कोई authorized user दूसरी client configuration से matching value भेज सकता है।
  • जब अलग लोग दोनों configurations नियंत्रित करते हैं, तब कोई एक सिरा पूरा contract लागू नहीं कर सकता।
  • command का सफल होना यह नहीं बताता कि server ने कौन से environment requests ठुकराए।

आखिरी बात महत्वपूर्ण है। OpenSSH भेजे गए variable को अनदेखा करके session जारी रख सकता है। यदि दूरस्थ shell उसी नाम को पहले से set करता है, तो केवल final value देखने वाला test forwarding को उस value का श्रेय दे सकता है जो कभी भेजी ही नहीं गई।

Wildcard भविष्य के स्थानीय state को दूरस्थ input बना देता है

SendEnv WORKFLOW_* का अर्थ “आज review किए गए variables” नहीं है। इसका अर्थ हर भविष्य के SSH client process में मौजूद सभी matching names है। कुछ सप्ताह बाद developer profile में WORKFLOW_DEBUG_DUMP, WORKFLOW_CUSTOMER या WORKFLOW_TOKEN_FILE जोड़ सकता है और पुराना SSH rule चुपचाप नया behavior अपना लेता है।

Locale forwarding दिखाता है कि यह दायरा कैसे बढ़ता है। बहुत से workstation configurations LANG और LC_* भेजते हैं ताकि interactive shell text ठीक दिखाए। मानव login के लिए यह उचित हो सकता है, पर noninteractive build या deploy account के लिए अपने आप उचित नहीं हो जाता। Locale sorting, character classes, date rendering और diagnostic messages बदलता है। output parse करने वाला job किसी secret के भेजे बिना भी टूट सकता है।

सबसे जोखिम वाले patterns अक्सर सुविधाजनक namespace जैसे दिखते हैं:

  • AWS_* में profiles, regions, credentials से जुड़े values और configuration paths आ सकते हैं।
  • GIT_* identity, tracing, alternate object directories या askpass behavior ले जा सकता है।
  • CI_* अक्सर साधारण build labels को provider context और temporary paths के साथ मिला देता है।
  • LC_* तब तक cosmetic लगता है जब तक script stable sorting या messages पर निर्भर न हो।
  • APP_* application के साथ बढ़ता रहता है और उसका एक security अर्थ शायद ही होता है।

पूरे namespace को safe न मानें। हर नाम को अलग जाँचें। DEPLOY_REGION जरूरी हो सकता है, जबकि AWS_PROFILE workstation context है। BUILD_REF जरूरी हो सकता है, जबकि GIT_CONFIG_COUNT Git का runtime configuration बदलता है। साझा prefix नामों को व्यवस्थित करता है, trust boundary नहीं बनाता।

Values credential न होकर भी context खोलते हैं। path username और repository layout बताता है। profile account या environment पहचानता है। trace flag दूरस्थ tool से command data shared log में लिखवा सकता है। agent इस context को बाद की actions में इस्तेमाल कर सकता है। Leak में अनचाहा प्रभाव और disclosure दोनों आते हैं, केवल secret strings नहीं।

सुरक्षित दिखने वाला अपवाद महीनों बाद फैल सकता है

यह leak अक्सर किसी एक साफ तौर पर लापरवाह बदलाव से नहीं, configuration drift से बनता है। developer पहले SendEnv APP_* जोड़ता है क्योंकि test को APP_COLOR=0 चाहिए। server उसे ठुकरा देता है, इसलिए कुछ नहीं होता। बाद में administrator उसी shared host पर दूसरी team के लिए AcceptEnv APP_* जोड़ता है। दोनों reviews अपनी जगह ठीक लगते हैं क्योंकि हर reviewer handshake का केवल आधा भाग देखता है।

अगला connection दोनों निष्क्रिय rules को जोड़ देता है। developer shell में अब APP_CUSTOMER=acme-lab, APP_TRACE=1 और APP_CONFIG=/Users/lee/work/private/config हैं। SSH client सब भेजता है, daemon सब स्वीकार करता है, और release fail होने पर diagnostic wrapper env चलाकर output को group-readable log में रखता है। token नहीं गया, लेकिन स्थानीय identity, customer context, path और trace flag बिना approval सीमा पार कर गए।

Server wildcard हटाने से भविष्य के sessions सुधरते हैं, पुराना log नहीं मिटता। इस खोज को छोटे incident की तरह सँभालें:

  1. व्यापक pattern स्वीकार करना बंद करें और daemon configuration validate करें।
  2. वे accounts, clients और समय अवधि खोजें जिनमें दोनों patterns एक साथ सक्रिय थे।
  3. approved logs में exposed names खोजें, sensitive values नहीं।
  4. पता करें कि किस value ने command behavior बदला या दूसरे user को context दिखाया।
  5. wildcard को exact names से बदलें और rejected classes के लिए canaries जोड़ें।

इसीलिए “server अभी इसे reject करता है” व्यापक client rule का बचाव नहीं है। dormant configuration के सक्रिय होने के क्षण पर अक्सर कोई owner नहीं होता। server strict हो तब भी अनावश्यक client offers हटाएँ, और clients सावधान हों तब भी server acceptance सीमित रखें।

उलटा drift भी होता है। server वर्षों से interactive users के लिए LC_* स्वीकार करता है, फिर automation image update ऐसा system client config जोड़ता है जो LC_* भेजता है। deploy job developer का चुना LC_COLLATE inherit करता है और files का क्रम बदल जाता है। शायद disclosure न हो, लेकिन उसी handshake ने integrity failure बनाया। Confidentiality और command behavior को साथ review करें।

वही configuration देखें जिसे SSH वास्तव में इस्तेमाल करेगा

किसी file को edit करने से पहले evaluated client configuration पढ़ें। OpenSSH का ssh -G Host, Match, includes, user config और system config लागू करके दिए गए destination का final result print करता है। जो file authoritative दिखती है वह किसी पहले value से हार सकती है या include से अतिरिक्त entries पा सकती है।

इसे workflow वाले account और उसी execution context से चलाएँ:

ssh -G deploy-prod |
  awk '$1 == "sendenv" || $1 == "setenv" { print }'

एक आम unsafe result ऐसा दिखता है:

sendenv LANG
sendenv LC_*
sendenv AWS_*
setenv WORKFLOW_KIND=deploy

ssh -G SendEnv से चुने गए current values नहीं, effective selection rules दिखाता है। इसलिए review output credentials नहीं उगलता। फिर भी names और patterns को उस process के environment से मिलाना होगा जो वास्तव में SSH शुरू करता है।

Values के बिना names capture करें:

env | sed 's/=.*//' | LC_ALL=C sort > local-env.names
grep -E '^(LANG|LC_|AWS_|WORKFLOW_)' local-env.names

ऊपर का regular expression inspection aid है, reusable policy नहीं। उसे ssh -G के हर pattern के अनुसार बदलें। यदि supervisor, IDE, agent या scheduled job SSH शुरू करता है, तो उसी process का environment देखें, interactive shell का नहीं। Environment inheritance process tree का अनुसरण करता है।

Server को अलग जाँचें। OpenSSH server पर sshd -T effective daemon settings validate और print करता है। Match blocks account को प्रभावित करें तो connection criteria दें:

sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep '^acceptenv'

Review में असली user, host और client address इस्तेमाल करें। documentation address केवल example में रखें। daemon reload करने से पहले sudo sshd -t भी चलाएँ; environment hardening के लिए remote access तोड़ना उचित नहीं है।

अलग client file allowlist को पढ़ने योग्य बनाती है

Credentials और remote inputs अलग करें
Sallyport SSH key रखता है; exact SendEnv list remote context नियंत्रित करती है।

Automation के लिए सबसे भरोसेमंद setup एक छोटी dedicated SSH configuration है जिसे -F से दिया जाए। ssh manual के अनुसार explicit file सामान्य per-user file को बदल देती है और system-wide client file को ignore कराती है। इससे workstation package या fleet setting बाद में locale wildcard जोड़कर workflow नहीं बदल सकती।

Host deploy-prod
    HostName deploy.example
    User deploybot
    IdentityFile ~/.ssh/deploy_ed25519
    IdentitiesOnly yes
    RequestTTY no
    SendEnv DEPLOY_REGION
    SendEnv BUILD_REF
    SetEnv WORKFLOW_KIND=deploy

इसे स्पष्ट रूप से चलाएँ:

ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release

SendEnv स्थानीय ssh process environment से value पढ़ता है। उसे तब इस्तेमाल करें जब value हर run में वैध रूप से बदलता हो। client SetEnv configuration में literal value लिखता है। उसे nonsecret constant label के लिए रखें, credential या ऐसा value जिसके update को लोग भूलेंगे, उसके लिए नहीं।

OpenSSH - से शुरू होने वाले SendEnv pattern के जरिए पहले चुने names हटाने देता है:

Host deploy-prod
    SendEnv -*
    SendEnv DEPLOY_REGION BUILD_REF

यह cleanup उस समय तक जमा selections पर लागू होता है। बाद का include या system rule names फिर जोड़ सकता है। इसलिए subtraction अंतिम automation boundary नहीं है। -F के साथ dedicated file में कम moving parts होते हैं और दूसरा engineer उसे एक screen में समझ सकता है।

Credentials इस contract से बाहर रखें। Forwarded token साधारण remote process state बन जाता है और child processes, debug output, crash reports, अनुमति मिलने पर /proc inspection या accidental env output तक पहुँच सकता है। SSH transport बचाता है, delivery के बाद value का पूरा जीवन नहीं।

Server को सीमित account के लिए exact names स्वीकार करने चाहिए

Session शुरू होने से पहले client variable ठुकराने की आखिरी जगह server है। Pseudo-terminal वाले TERM अपवाद को छोड़कर OpenSSH default में कोई variable स्वीकार नहीं करता। यह global default बनाए रखें और workflow owner account के लिए केवल exact names जोड़ें।

Match User deploybot
    AcceptEnv DEPLOY_REGION
    AcceptEnv BUILD_REF
    AcceptEnv WORKFLOW_KIND

AcceptEnv APP_*, AcceptEnv AWS_* या अकेला wildcard इस्तेमाल न करें। OpenSSH का sshd_config manual स्पष्ट चेतावनी देता है कि कुछ environment variables restricted user environment को bypass कर सकते हैं। Wildcard बिना किसी अगले server change के भविष्य के names भी अनुमति देता है।

व्यापक global AcceptEnv हर matching account को कमजोर करता है। संकरा Match User block पहले से globally accepted names को नहीं मिटाता; entries जुड़ सकती हैं। यदि interactive users को locale forwarding चाहिए और deploy account को नहीं, तो global locale rule से शुरुआत न करें। केवल सही users या groups को अनुमति दें और sshd -T -C से हर connection जाँचें।

Server-side SetEnv अलग control है। वह child sessions में values set करता है और defaults, AcceptEnv या PermitUserEnvironment से आए values को override करता है। यदि constant server का है, तो उसे server पर set करें, client से स्वीकार न करें।

PermitUserEnvironment एक और source है। वह ~/.ssh/environment और authorized_keys के environment= options को नियंत्रित करता है, और OpenSSH उसे default में बंद रखता है। केवल AcceptEnv देखने वाला audit इसे चूक सकता है। बिना खास account design के इसे बंद रखें और जरूरत हो तो इसके patterns को उसी contract review में जोड़ें।

Exact-name allowlist names नियंत्रित करती है, values नहीं। Allowed DEPLOY_REGION में whitespace, shell metacharacter, newline या prohibited region हो सकता है। SSH protocol value को data की तरह ले जाता है, लेकिन receiving script eval, unquoted expansion, generated configuration या command string से उसे syntax बना सकता है।

हर accepted value को remote entry point पर validate करें:

case ${DEPLOY_REGION-} in
    us-east-1|us-west-2) ;;
    *)
        printf 'invalid DEPLOY_REGION\n' >&2
        exit 64
        ;;
esac

case ${BUILD_REF-} in
    [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*)
        ;;
    *)
        printf 'invalid BUILD_REF\n' >&2
        exit 64
        ;;
esac

Validation वास्तविक contract से मेल खाना चाहिए। छोटा shell pattern केवल shape check दिखाता है; release को पूरा commit identifier चाहिए तो exact length लागू करें और repository में उसकी मौजूदगी जाँचें। Validator इतना permissive न हो कि केवल empty string रोके।

Edit के बाद indentation पर भरोसा न करके effective result देखें:

sudo sshd -t
sudo sshd -T \
  -C user=deploybot,host=deploy.example,addr=192.0.2.44 |
  grep -E '^(acceptenv|permituserenvironment|setenv)'

इस output को configuration review के साथ रखें। यह दर्ज करता है कि tested connection के लिए daemon ने वास्तव में क्या parse किया, जो includes से भरे directory के एक fragment के screenshot से अधिक उपयोगी है।

Remote process में required values और rejected canaries साबित करें

MCP agents को एक gateway दें
कोई भी MCP-compatible agent bundled sp mcp से SSH request कर सकता है।

उपयोगी test remote process में positive और negative दोनों cases जाँचता है। हर required value को साफ marker दें, पुराने broad patterns से match होने वाले canaries set करें, dedicated file के साथ noninteractive session चलाएँ और contract गलत हो तो remote shell को fail कराएँ।

यह sequence client से केवल DEPLOY_REGION, BUILD_REF और fixed WORKFLOW_KIND की अपेक्षा करता है:

export DEPLOY_REGION='env-audit-region'
export BUILD_REF='env-audit-ref'
export AWS_PROFILE='must-not-cross'
export LC_AUDIT_CANARY='must-not-cross'
export APP_PRIVATE_PATH='must-not-cross'

ssh -F ./deploy-ssh.conf -T deploy-prod 'sh -s' <<'REMOTE'
set -eu

test "$(printenv DEPLOY_REGION)" = 'env-audit-region'
test "$(printenv BUILD_REF)" = 'env-audit-ref'
test "$(printenv WORKFLOW_KIND)" = 'deploy'

for name in AWS_PROFILE LC_AUDIT_CANARY APP_PRIVATE_PATH; do
    if printenv "$name" >/dev/null 2>&1; then
        printf 'unexpected forwarded variable: %s\n' "$name" >&2
        exit 1
    fi
done

printf '%s\n' 'SSH environment contract passed'
REMOTE

Expected output एक line है:

SSH environment contract passed

फिर एक required local value unset करके negative test चलाएँ। SendEnv local process में absent name नहीं भेज सकता, इसलिए remote assertion fail होना चाहिए:

unset BUILD_REF
if ssh -F ./deploy-ssh.conf -T deploy-prod 'test -n "$BUILD_REF"'; then
    printf '%s\n' 'test failed: BUILD_REF appeared unexpectedly' >&2
    exit 1
fi

यह optional forwarded value और required workflow input में फर्क करता है। यदि job को BUILD_REF के बिना fail होना चाहिए, launcher में ${BUILD_REF:?BUILD_REF is required} भी रखें। Remote check फिर भी जरूरी है क्योंकि वह transport contract और server rejection जाँचता है।

Canaries audit में मिले हर wildcard या questionable class को cover करें और साफ तौर पर fake हों। Leakage test में real credential कभी न रखें; failure उसी value को log में लिख सकता है जिसका जोखिम आप साबित कर रहे हैं।

एक सफल canary run यह साबित नहीं करता कि कोई भी कल्पनीय variable नहीं जा सकता। वह एक configuration और एक process environment में नामित negative cases साबित करता है। उसे दो static checks से जोड़ें: ssh -G में केवल exact SendEnv names हों और sshd -T -C में केवल expected AcceptEnv names। * या ? दिखे तो future environment की पूरी सूची test नहीं कर सकता।

हर अलग launcher से contract test चलाएँ। Developer shell, CI worker, editor task और autonomous agent एक ही binary को अलग configuration paths और environments से चला सकते हैं। Dedicated file का path launcher में दर्ज करें, केवल interactive alias में नहीं।

Final environment देखना और SSH contribution साबित करना अलग बातें हैं। यदि /etc/profile पहले से DEPLOY_REGION=us-east-1 set करता है और client वही value भेजता है, server request reject करके भी positive assertion पास करा सकता है। Unique marker और missing-input test दोनों चलाएँ।

Test यह दावा नहीं करता कि remote environment में केवल तीन variables हैं। सामान्य OpenSSH session को HOME, USER, SHELL, PATH और SSH connection metadata भी मिलते हैं, और startup files या wrappers और values जोड़ सकते हैं। Assertion केवल client-contributed हिस्सा साबित करता है। पूरे minimal environment की जरूरत हो तो server baseline अलग audit करें।

Command construction SendEnv को पूरी तरह bypass कर सकता है

SendEnv साफ करना local shell को remote command string में variables expand करने से नहीं रोकता। यह अलग data path है:

ssh deploy-prod "release '$TENANT' '$TOKEN'"

Local shell ssh चलने से पहले दोनों values बदल देता है। वे encrypted command request में जाते हैं, env request में नहीं, इसलिए AcceptEnv उन्हें रोक नहीं सकता। Launcher command कैसे बनाता और record करता है, उसके अनुसार वे process inspection, shell history, CI logs या errors में भी दिख सकते हैं।

यह prefix local SSH process को बदलता है, लेकिन name configuration में चुना गया हो तभी पार होता है:

DEPLOY_REGION=west ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release

Teams इन cases को अक्सर मिला देती हैं। “SSH चलते समय value environment में था” यह नहीं साबित करता कि forwarding ने भेजा; “हमने SendEnv बंद किया” यह नहीं साबित करता कि wrapper ने उसे arguments या standard input में interpolate नहीं किया। असली channel trace करें।

Remote startup code एक और source है। Login shell, /etc/environment, PAM, forced command, sudo, service manager या container launcher SSH के स्वीकार करने के बाद values हटा, बदल या जोड़ सकता है। Marker न मिले तो client decisions के लिए ssh -vvv, permitted server logs और application wrapper से पहले छोटा command चलाएँ। तुरंत AcceptEnv न बढ़ाएँ।

sudo को अलग जाँच चाहिए। sudoers environment reset, selected names retain या preservation request allow कर सकता है, लेकिन वह केवल privileged child तक पहुँचने वाला environment बदलता है। Value उससे पहले unprivileged SSH session में आ चुका था, जहाँ scripts और wrappers उसे देख सकते थे। दोनों layers अलग configure करें।

Remote host passive pipe नहीं है। Remote account नियंत्रित करने वाला व्यक्ति आम तौर पर process environment print कर सकता है, और administrator machine नियंत्रित करता है। यदि security requirement कहती है कि remote host कोई value कभी न जाने, तो उसे SSH से किसी रूप में न भेजें।

Routine logs में पूरा env dump न करें। Approved audit में पहले names capture करें और values केवल fake markers के लिए दिखाएँ। पूरा dump unrelated variables को भी incident material बना सकता है।

Agent के SSH को छोटी process boundary चाहिए

एक Mac app custody रखता है
Signed menu-bar app vault core को process में रखता है, अलग daemon नहीं चाहिए।

Autonomous agent अक्सर उस terminal, editor या orchestrator का environment inherit करता है जिसने उसे शुरू किया। वह environment कई repositories और accounts पर काम करने वाले मानव के लिए बना है, एक remote action के लिए नहीं। उसके namespaces भेजना agent को अतिरिक्त context और remote tools को unreviewed inputs देता है।

Workflow को explicit local environment और explicit SSH configuration दोनों के साथ शुरू करें। Minimal wrapper दो changing values माँग सकता है, unrelated inherited state हटा सकता है और केवल client की जरूरत वापस दे सकता है:

#!/bin/sh
set -eu
: "${DEPLOY_REGION:?DEPLOY_REGION is required}"
: "${BUILD_REF:?BUILD_REF is required}"

exec env -i \
  HOME="$HOME" \
  PATH='/usr/bin:/bin:/usr/sbin:/sbin' \
  DEPLOY_REGION="$DEPLOY_REGION" \
  BUILD_REF="$BUILD_REF" \
  ssh -F ./deploy-ssh.conf deploy-prod /usr/local/bin/release

Operating system के अनुसार PATH और required inputs बदलें, और list explicit रखें। यहाँ HOME इसलिए है कि OpenSSH known_hosts और identity file path इस्तेमाल कर सकता है। Managed runner ये paths दूसरी options से दे तो HOME भी हटाएँ।

Mac पर agent-operated SSH के लिए Sallyport SSH key को encrypted vault में रख सकता है और bundled sp-ssh से action चला सकता है, इसलिए agent को credential नहीं मिलता। इससे credential custody बदलती है, पर vague remote environment contract सही नहीं हो जाता; allowed command के आसपास exact-name test बनाए रखें।

Shortcut के रूप में स्थानीय cloud credentials forward न करें। Remote workload को अपनी narrowly scoped identity दें या credential रखने वाले gateway से action कराएँ। Operator का ambient credential remote process में copy करना दो trust boundaries जोड़ देता है और revocation कठिन बनाता है।

Configuration बदलने पर contract को executable रखें

Environment rules drift करते हैं क्योंकि client packages defaults जोड़ते हैं, administrators daemon snippets जोड़ते हैं और workflows नए inputs लेते हैं। Prose standard यह drift नहीं पकड़ेगा। Dedicated client file, server account configuration और canary assertion को साथ review करें।

इनमें किसी बदलाव के बाद assertion चलाएँ:

  • SSH client या operating-system packages
  • user और system SSH configuration includes
  • sshd_config, PAM, shell startup files या forced commands
  • agent launcher, CI runner, service manager या container image
  • workflow की required input list

नए variable को interface change मानें। लिखें कि remote command को वह क्यों चाहिए, value client का है या server का, उसमें sensitive context है या नहीं, और कौन सा test दूसरी जगह उसकी अनुपस्थिति साबित करता है। जवाब न हों तो wildcard बढ़ाने के बजाय validated command input दें या remote action redesign करें।

Failure स्पष्ट रखें। Forwarding टूटने पर remote default पर चुपचाप गिरने वाला deployment उस deployment से कठिन और अधिक खतरनाक है जो missing marker पर रुकता है। Required inputs local launcher और remote entry point दोनों पर fail होने चाहिए।

अंत में account को remote side से भी review करें। Perfect SendEnv list ऐसे deploy account की रक्षा नहीं करती जो arbitrary shells चला सकता है, दूसरे users के process environments पढ़ सकता है या अपनी startup files बदल सकता है। इस input channel को exact बनाएँ, behavior साबित करें और remote command की authority इतनी सीमित रखें कि unexpected value unrelated action न बन सके।

सामान्य प्रश्न

क्या SSH default में सभी local environment variables भेजता है?

नहीं। OpenSSH SendEnv से चुने names और client SetEnv के literal values भेजता है, और server को आम तौर पर AcceptEnv से स्वीकार करना होता है। pseudo-terminal में TERM का अलग नियम है।

SendEnv और SetEnv में क्या अंतर है?

SendEnv local SSH process से variable का current value लेता है। Client SetEnv fixed NAME=VALUE देता है, इसलिए वह nonsecret constant label के लिए ठीक है, per-run input के लिए नहीं।

क्या AcceptEnv client के बिना भेजे variable पा सकता है?

नहीं। वह request की अनुमति देता है, value बनाता नहीं। वही नाम server configuration, PAM, shell startup या wrapper से आ सकता है, इसलिए source पहचानें।

क्या LANG और LC_* forward करना सुरक्षित है?

Interactive accounts के लिए यह उचित हो सकता है, पर automation के लिए अक्सर बहुत व्यापक है। Locale sorting, parsing और diagnostics बदल सकता है।

क्या inherited SendEnv rules हटाए जा सकते हैं?

- prefix वाला SendEnv pattern पहले selections हटा सकता है। बाद के rules फिर जोड़ सकते हैं, इसलिए ssh -F वाली dedicated file audit करना आसान है।

किसी host पर लागू SendEnv rules कैसे देखें?

Workflow account से ssh -G host चलाकर sendenv और setenv filter करें। यह evaluated rules दिखाता है, current values नहीं।

Remote host पर forwarded variable क्यों गायब है?

वह local में unset, client में unselected, server में rejected या बाद की layer में removed हो सकता है। हर gate इसी क्रम में fake marker से जाँचें।

क्या ssh -T पूरा environment forwarding रोक देता है?

नहीं। -T pseudo-terminal और TERM का खास रास्ता बंद करता है। दूसरे selected और accepted names अब भी जा सकते हैं।

क्या environment variables SSH credentials के लिए सुरक्षित हैं?

वे खराब transport हैं। स्वीकार होने के बाद credential remote process state बनता है और children, logs, diagnostics या inspection में जा सकता है। Remote identity या gateway इस्तेमाल करें।

SSH environment forwarding कितनी बार test करना चाहिए?

Packages, configuration, daemon settings, launchers, images या workflow inputs बदलने पर canary assertion चलाएँ। इसे normal review का हिस्सा रखें।

Sallyport

Sallyport आपके AI एजेंट के लिए API कॉल और SSH कमांड चलाता है। कुंजियाँ आपके Mac पर एक लोकल वॉल्ट में रहती हैं; आप हर रन को स्वीकृत करते हैं और हर क्रिया एक सीलबंद जर्नल में दर्ज होती है।

© 2026 Sallyport · Apache-2.0 के तहत ओपन सोर्स · Oleg Sotnikov