@@ -103,7 +103,7 @@ export default class Acode {
103103 createServer : ( options ) => TerminalManager . createServerTerminal ( options ) ,
104104 get : ( id ) => TerminalManager . getTerminal ( id ) ,
105105 getAll : ( ) => TerminalManager . getAllTerminals ( ) ,
106- write : ( id , data ) => TerminalManager . writeToTerminal ( id , data ) ,
106+ write : ( id , data ) => this . #secureTerminalWrite ( id , data ) ,
107107 clear : ( id ) => TerminalManager . clearTerminal ( id ) ,
108108 close : ( id ) => TerminalManager . closeTerminal ( id ) ,
109109 themes : {
@@ -162,6 +162,101 @@ export default class Acode {
162162 this . define ( "toInternalUrl" , helpers . toInternalUri ) ;
163163 }
164164
165+ /**
166+ * Secure terminal write with command validation
167+ * Prevents execution of malicious or dangerous commands through plugin API
168+ * @param {string } id - Terminal ID
169+ * @param {string } data - Data to write
170+ */
171+ #secureTerminalWrite( id , data ) {
172+ if ( typeof data !== "string" ) {
173+ console . warn ( "Terminal write data must be a string" ) ;
174+ return ;
175+ }
176+
177+ // List of potentially dangerous commands/patterns to block
178+ const dangerousPatterns = [
179+ // System commands that can cause damage
180+ / ^ \s * r m \s + - r f ? \s + \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
181+ / ^ \s * r m \s + - r f ? \s + \* [ ^ \r \n ] * [ \r \n ] ? $ / m,
182+ / ^ \s * r m \s + - r f ? \s + ~ [ ^ \r \n ] * [ \r \n ] ? $ / m,
183+ / ^ \s * m k f s \. [ ^ \r \n ] * [ \r \n ] ? $ / m,
184+ / ^ \s * d d \s + i f = \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
185+ / ^ \s * : ( ) { : | : & } ; : [ ^ \r \n ] * [ \r \n ] ? $ / m, // Fork bomb
186+ / ^ \s * s u d o \s + d d \s + i f = \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
187+ / ^ \s * s u d o \s + r m \s + - r f ? \s + \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
188+ / ^ \s * c u r l \s + [ ^ \r \n ] * \| \s * s h [ ^ \r \n ] * [ \r \n ] ? $ / m,
189+ / ^ \s * w g e t \s + [ ^ \r \n ] * \| \s * s h [ ^ \r \n ] * [ \r \n ] ? $ / m,
190+ / ^ \s * b a s h \s + < \s * \( [ ^ \r \n ] * [ \r \n ] ? $ / m,
191+ / ^ \s * s h \s + < \s * \( [ ^ \r \n ] * [ \r \n ] ? $ / m,
192+
193+ // Network-based attacks
194+ / ^ \s * n c \s + - l \s + - p \s + \d + [ ^ \r \n ] * [ \r \n ] ? $ / m,
195+ / ^ \s * n c a t \s + - l \s + - p \s + \d + [ ^ \r \n ] * [ \r \n ] ? $ / m,
196+ / ^ \s * p y t h o n \s + .* S i m p l e H T T P S e r v e r [ ^ \r \n ] * [ \r \n ] ? $ / m,
197+ / ^ \s * p y t h o n \s + .* h t t p \. s e r v e r [ ^ \r \n ] * [ \r \n ] ? $ / m,
198+
199+ // Process manipulation
200+ / ^ \s * k i l l \s + - 9 \s + 1 \s * [ \r \n ] ? $ / m,
201+ / ^ \s * k i l l a l l \s + - 9 \s + \* [ ^ \r \n ] * [ \r \n ] ? $ / m,
202+
203+ // File system manipulation
204+ / ^ \s * c h m o d \s + 7 7 7 \s + \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
205+ / ^ \s * c h o w n \s + [ ^ \s ] + \s + \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
206+
207+ // Sensitive file access attempts
208+ / ^ \s * c a t \s + \/ e t c \/ p a s s w d [ ^ \r \n ] * [ \r \n ] ? $ / m,
209+ / ^ \s * c a t \s + \/ e t c \/ s h a d o w [ ^ \r \n ] * [ \r \n ] ? $ / m,
210+ / ^ \s * c a t \s + \/ r o o t \/ [ ^ \r \n ] * [ \r \n ] ? $ / m,
211+
212+ // Only block null bytes
213+ / \x00 / g,
214+ ] ;
215+
216+ // Check for dangerous patterns
217+ for ( const pattern of dangerousPatterns ) {
218+ if ( pattern . test ( data ) ) {
219+ console . warn (
220+ `Blocked potentially dangerous terminal command: ${ data . substring ( 0 , 50 ) } ...` ,
221+ ) ;
222+ toast ( "Potentially dangerous command blocked for security" , 3000 ) ;
223+ return ;
224+ }
225+ }
226+
227+ // Additional checks for suspicious character sequences
228+ if ( data . includes ( "$(" ) && data . includes ( ")" ) ) {
229+ const commandSubstitution = / \$ \( [ ^ ) ] * \) / g;
230+ const matches = data . match ( commandSubstitution ) ;
231+ if ( matches ) {
232+ for ( const match of matches ) {
233+ // Check if command substitution contains dangerous commands
234+ for ( const pattern of dangerousPatterns ) {
235+ if ( pattern . test ( match ) ) {
236+ console . warn (
237+ `Blocked command substitution with dangerous content: ${ match } ` ,
238+ ) ;
239+ toast ( "Command substitution blocked for security" , 3000 ) ;
240+ return ;
241+ }
242+ }
243+ }
244+ }
245+ }
246+
247+ // Sanitize data length to prevent memory exhaustion
248+ const maxLength = 64 * 1024 ; // 64KB max per write
249+ if ( data . length > maxLength ) {
250+ console . warn (
251+ `Terminal write data truncated - exceeded ${ maxLength } characters` ,
252+ ) ;
253+ data = data . substring ( 0 , maxLength ) + "\n[Data truncated for security]\n" ;
254+ }
255+
256+ // If all security checks pass, proceed with writing
257+ return TerminalManager . writeToTerminal ( id , data ) ;
258+ }
259+
165260 /**
166261 * Define a module
167262 * @param {string } name
0 commit comments