Skip to content
92 changes: 46 additions & 46 deletions CheckList.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@
- [x] systeminfo
- [x] hostname
- [x] ver
- [ ] vol
- [ ] set
- [x] vol
- [x] set
- [ ] setx
- [ ] wmic
- [ ] driverquery
- [ ] tasklist
- [ ] taskkill
- [ ] sfc
- [ ] chkdsk
- [ ] label
- [ ] fsutil
- [ ] assoc
- [ ] ftype
- [x] wmic
- [x] driverquery
- [x] tasklist
- [x] taskkill
- [x] sfc
- [x] chkdsk
- [x] label
- [x] fsutil
- [x] assoc
- [x] ftype

---

Expand All @@ -33,46 +33,46 @@
- [x] rd / rmdir
- [x] del / erase
- [x] copy
- [ ] xcopy
- [ ] robocopy
- [x] xcopy
- [x] robocopy
- [x] move
- [ ] rename / ren
- [ ] attrib
- [x] rename / ren
- [x] attrib
- [x] tree
- [x] type
- [ ] more
- [ ] find
- [ ] findstr
- [ ] sort
- [ ] fc
- [ ] forfiles
- [ ] compact
- [ ] replace
- [x] more
- [x] find
- [x] findstr
- [x] sort
- [x] fc
- [x] forfiles
- [x] compact
- [x] replace

---

## 🌐 Network & Internet Commands
- [x] ping
- [ ] ipconfig
- [ ] getmac
- [ ] nslookup
- [ ] netstat
- [ ] tracert
- [x] ipconfig
- [x] getmac
- [x] nslookup
- [x] netstat
- [x] tracert
- [ ] pathping
- [ ] arp
- [ ] route
- [ ] netsh
- [x] arp
- [x] route
- [x] netsh
- [ ] ftp
- [ ] tftp
- [ ] telnet
- [x] telnet
- [ ] nbtstat
- [ ] net
- [ ] net user
- [ ] net use
- [ ] net share
- [ ] net start
- [ ] net stop
- [ ] net session
- [x] net
- [x] net user
- [x] net use
- [x] net share
- [x] net start
- [x] net stop
- [x] net session
- [ ] curl
- [ ] powershell

Expand Down Expand Up @@ -119,8 +119,8 @@
- [ ] choice
- [x] timeout
- [ ] call
- [ ] start
- [ ] taskkill
- [x] start
- [x] taskkill
- [ ] schtasks
- [ ] for
- [ ] if
Expand Down Expand Up @@ -158,11 +158,11 @@
- [ ] mode
- [ ] print
- [ ] subst
- [ ] clip
- [ ] msg
- [x] clip
- [x] msg
- [x] ver
- [ ] verify
- [ ] vol
- [x] verify
- [x] vol

---

Expand Down
79 changes: 78 additions & 1 deletion src/main/java/com/mycmd/App.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.mycmd;

import com.mycmd.commands.*;
import com.mycmd.utils.StringUtils;

import java.util.*;
import java.util.Scanner;
Expand Down Expand Up @@ -76,77 +75,155 @@ private static String resolveAliases(String input, ShellContext context) {
private static final class CommandNames {
private CommandNames() {}
private static final String ALIAS = "alias";
private static final String ARP = "arp";
private static final String ASSOC = "assoc";
private static final String ATTRIB = "attrib";
private static final String CD = "cd";
private static final String CHKDSK = "chkdsk";
private static final String CHOICE = "choice";
private static final String CLEARHISTORY = "clearhistory";
private static final String CLIP = "clip";
private static final String CLS = "cls";
private static final String COLOR = "color";
private static final String COMPACT = "compact";
private static final String COPY = "copy";
private static final String DATE = "date";
private static final String DEL = "del";
private static final String DIR = "dir";
private static final String DRIVERQUERY = "driverquery";
private static final String ECHO = "echo";
private static final String EXIT = "exit";
private static final String FC = "fc";
private static final String FIND = "find";
private static final String FINDSTR = "findstr";
private static final String FORFILES = "forfiles";
private static final String FSUTIL = "fsutil";
private static final String FTYPE = "ftype";
private static final String GETMAC = "getmac";
private static final String HELP = "help";
private static final String HISTORY = "history";
private static final String HOSTNAME = "hostname";
private static final String IPCONFIG = "ipconfig";
private static final String LABEL = "label";
private static final String LS = "ls";
private static final String MKDIR = "mkdir";
private static final String MORE = "more";
private static final String MOVE = "move";
private static final String MSG = "msg";
private static final String NET = "net";
private static final String NETSH = "netsh";
private static final String NETSTAT = "netstat";
private static final String NSLOOKUP = "nslookup";
private static final String PATH = "path";
private static final String PAUSE = "pause";
private static final String PING = "ping";
private static final String PWD = "pwd";
private static final String REM = "rem";
private static final String RENAME = "rename";
private static final String REPLACE = "replace";
private static final String RMDIR = "rmdir";
private static final String ROBOCOPY = "robocopy";
private static final String ROUTE = "route";
private static final String SET = "set";
private static final String SFC = "sfc";
private static final String SHUTDOWN = "shutdown";
private static final String SORT = "sort";
private static final String START = "start";
private static final String SYSTEMINFO = "systeminfo";
private static final String TASKKILL = "taskkill";
private static final String TASKLIST = "tasklist";
private static final String TELNET = "telnet";
private static final String TIME = "time";
private static final String TIMEOUT = "timeout";
private static final String TITLE = "title";
private static final String TOUCH = "touch";
private static final String TRACERT = "tracert";
private static final String TREE = "tree";
private static final String TYPE = "type";
private static final String UNALIAS = "unalias";
private static final String UPTIME = "uptime";
private static final String VER = "ver";
private static final String VERIFY = "verify";
private static final String VOL = "vol";
private static final String WHOAMI = "whoami";
private static final String WMIC = "wmic";
private static final String XCOPY = "xcopy";
}

private static void registerCommands(Map<String, Command> commands) {
commands.put(CommandNames.ALIAS, new AliasCommand());
commands.put(CommandNames.ARP, new ArpCommand());
commands.put(CommandNames.ASSOC, new AssocCommand());
commands.put(CommandNames.ATTRIB, new AttribCommand());
commands.put(CommandNames.CD, new CdCommand());
commands.put(CommandNames.CHKDSK, new ChkdskCommand());
commands.put(CommandNames.CHOICE, new ChoiceCommand());
commands.put(CommandNames.CLEARHISTORY, new ClearHistoryCommand());
commands.put(CommandNames.CLIP, new ClipCommand());
commands.put(CommandNames.CLS, new ClsCommand());
commands.put(CommandNames.COLOR, new ColorCommand());
commands.put(CommandNames.COMPACT, new CompactCommand());
commands.put(CommandNames.COPY, new CopyCommand());
commands.put(CommandNames.DATE, new DateCommand());
commands.put(CommandNames.DEL, new DelCommand());
commands.put(CommandNames.DIR, new DirCommand());
commands.put(CommandNames.DRIVERQUERY, new DriverqueryCommand());
commands.put(CommandNames.ECHO, new EchoCommand());
commands.put(CommandNames.EXIT, new ExitCommand());
commands.put(CommandNames.FC, new FcCommand());
commands.put(CommandNames.FIND, new FindCommand());
commands.put(CommandNames.FINDSTR, new FindstrCommand());
commands.put(CommandNames.FORFILES, new ForfilesCommand());
commands.put(CommandNames.FSUTIL, new FsutilCommand());
commands.put(CommandNames.FTYPE, new FtypeCommand());
commands.put(CommandNames.GETMAC, new GetmacCommand());
commands.put(CommandNames.HELP, new HelpCommand(commands));
commands.put(CommandNames.HISTORY, new HistoryCommand());
commands.put(CommandNames.HOSTNAME, new HostnameCommand());
commands.put(CommandNames.IPCONFIG, new IpConfig());
commands.put(CommandNames.LABEL, new LabelCommand());
commands.put(CommandNames.LS, new LsCommand());
commands.put(CommandNames.MKDIR, new MkdirCommand());
commands.put(CommandNames.MORE, new MoreCommand());
commands.put(CommandNames.MOVE, new MoveCommand());
commands.put(CommandNames.MSG, new MsgCommand());
commands.put(CommandNames.NET, new NetCommand());
commands.put(CommandNames.NETSH, new NetshCommand());
commands.put(CommandNames.NETSTAT, new NetstatCommand());
commands.put(CommandNames.NSLOOKUP, new NslookupCommand());
commands.put(CommandNames.PATH, new PathCommand());
commands.put(CommandNames.PAUSE, new PauseCommand());
commands.put(CommandNames.PING, new PingCommand());
commands.put(CommandNames.PWD, new PwdCommand());
commands.put(CommandNames.REM, new RemCommand());
commands.put(CommandNames.RENAME, new RenameCommand());
commands.put(CommandNames.REPLACE, new ReplaceCommand());
commands.put(CommandNames.RMDIR, new RmdirCommand());
commands.put(CommandNames.ROBOCOPY, new RobocopyCommand());
commands.put(CommandNames.ROUTE, new RouteCommand());
commands.put(CommandNames.SET, new SetCommand());
commands.put(CommandNames.SFC, new SfcCommand());
commands.put(CommandNames.SHUTDOWN, new ShutdownCommand());
commands.put(CommandNames.SORT, new SortCommand());
commands.put(CommandNames.START, new StartCommand());
commands.put(CommandNames.SYSTEMINFO, new SysteminfoCommand());
commands.put(CommandNames.TASKKILL, new TaskkillCommand());
commands.put(CommandNames.TASKLIST, new TasklistCommand());
commands.put(CommandNames.TELNET, new TelnetCommand());
commands.put(CommandNames.TIME, new TimeCommand());
commands.put(CommandNames.TIMEOUT, new TimeoutCommand());
commands.put(CommandNames.TITLE, new TitleCommand());
commands.put(CommandNames.TOUCH, new TouchCommand());
commands.put(CommandNames.TRACERT, new TracertCommand());
commands.put(CommandNames.TREE, new TreeCommand());
commands.put(CommandNames.TYPE, new TypeCommand());
commands.put(CommandNames.UNALIAS, new UnaliasCommand());
commands.put(CommandNames.UPTIME, new UptimeCommand());
commands.put(CommandNames.VER, new VersionCommand());
commands.put(CommandNames.VERIFY, new VerifyCommand());
commands.put(CommandNames.VOL, new VolCommand());
commands.put(CommandNames.WHOAMI, new WhoamiCommand());
commands.put(CommandNames.WMIC, new WmicCommand());
commands.put(CommandNames.XCOPY, new XcopyCommand());
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/mycmd/StringUtils.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mycmd.utils;
package com.mycmd;

import java.util.Collection;
import java.util.Objects;
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/com/mycmd/commands/ArpCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.mycmd.commands;

import com.mycmd.Command;
import com.mycmd.ShellContext;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

Comment on lines +5 to +8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Harden ARP execution: no shell string, no deadlocks; add timeout + cwd.

  • Replace cmd/sh string execution with arg list (prevents injection/quoting bugs).
  • Merge stderr, close resources, set cwd, add timeout and exit code.

Apply:

 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
@@
-        try {
-            StringBuilder cmdBuilder = new StringBuilder("arp");
-            for (String arg : args) {
-                cmdBuilder.append(" ").append(arg);
-            }
-            
-            // Default to -a if no args provided
-            if (args.length == 0) {
-                cmdBuilder.append(" -a");
-            }
-            
-            ProcessBuilder pb = new ProcessBuilder();
-            String os = System.getProperty("os.name").toLowerCase();
-            
-            if (os.contains("win")) {
-                pb.command("cmd.exe", "/c", cmdBuilder.toString());
-            } else {
-                pb.command("sh", "-c", cmdBuilder.toString());
-            }
-            
-            Process process = pb.start();
-            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
-            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
-            
-            String line;
-            while ((line = reader.readLine()) != null) {
-                System.out.println(line);
-            }
-            
-            while ((line = errorReader.readLine()) != null) {
-                System.err.println(line);
-            }
-            
-            process.waitFor();
-            
-        } catch (Exception e) {
-            System.out.println("Error executing arp: " + e.getMessage());
-        }
+        try {
+            List<String> cmd = new ArrayList<>();
+            cmd.add("arp");
+            if (args.length == 0) {
+                cmd.add("-a");
+            } else {
+                cmd.addAll(Arrays.asList(args));
+            }
+
+            ProcessBuilder pb = new ProcessBuilder(cmd);
+            pb.directory(context.getCurrentDir());
+            pb.redirectErrorStream(true);
+
+            Process process = pb.start();
+            try (BufferedReader reader =
+                         new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    System.out.println(line);
+                }
+            }
+            boolean finished = process.waitFor(30, TimeUnit.SECONDS);
+            if (!finished) {
+                process.destroyForcibly();
+                System.err.println("arp timed out after 30s.");
+            } else if (process.exitValue() != 0) {
+                System.err.println("arp exited with code " + process.exitValue());
+            }
+        } catch (InterruptedException ie) {
+            Thread.currentThread().interrupt();
+            System.err.println("arp interrupted.");
+        } catch (IOException ioe) {
+            System.err.println("Error executing arp: " + ioe.getMessage());
+        }

Also applies to: 20-57

🤖 Prompt for AI Agents
In src/main/java/com/mycmd/commands/ArpCommand.java around lines 6-9 (and apply
same changes to lines 20-57), the current approach builds and runs a shell
command string which is vulnerable to injection/quoting issues and can deadlock;
replace it with a ProcessBuilder using a List<String> of arguments (no "/bin/sh
-c"), call redirectErrorStream(true) to merge stderr, set the working directory
via setDirectory(...), start the process, close all I/O streams in finally (or
try-with-resources) to avoid leaks, wait for completion with a timeout using
process.waitFor(timeout, unit) and if it times out call
process.destroyForcibly(), then check the exit code and handle non-zero exit
appropriately; ensure you capture and log process output safely without blocking
and do not rely on a shell string.

/**
* Displays and modifies the IP-to-Physical address translation tables (ARP cache).
*
* Usage:
* - arp -a : Display ARP cache
*/
public class ArpCommand implements Command {

@Override
public void execute(String[] args, ShellContext context) throws IOException {
try {
StringBuilder cmdBuilder = new StringBuilder("arp");
for (String arg : args) {
cmdBuilder.append(" ").append(arg);
}

// Default to -a if no args provided
if (args.length == 0) {
cmdBuilder.append(" -a");
}

ProcessBuilder pb = new ProcessBuilder();
String os = System.getProperty("os.name").toLowerCase();

if (os.contains("win")) {
pb.command("cmd.exe", "/c", cmdBuilder.toString());
} else {
pb.command("sh", "-c", cmdBuilder.toString());
}

Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

while ((line = errorReader.readLine()) != null) {
System.err.println(line);
}

process.waitFor();

} catch (Exception e) {
System.out.println("Error executing arp: " + e.getMessage());
}
}

@Override
public String description() {
return "Displays and modifies the IP-to-Physical address translation tables.";
}

@Override
public String usage() {
return "arp [-a] [-d ip_addr] [-s ip_addr eth_addr]";
}
}
Loading
Loading