Semgrep: Semantic grep for code(semgrep.dev)
semgrep.dev
Semgrep: Semantic grep for code
https://semgrep.dev
109 comments
I agree it is an excellent tool. At GitLab we released our Semgrep integration today https://news.ycombinator.com/item?id=26903114
"GitLab SAST historically has been powered by over a dozen open-source static analysis security analyzers. These analyzers have proactively identified millions of vulnerabilities for developers using GitLab every month. Each of these analyzers is language-specific and has different technology approaches to scanning. These differences produce overhead for updating, managing, and maintaining additional features we build on top of these tools, and they create confusion for anyone attempting to debug.
The GitLab Static Analysis team is continuously evaluating new security analyzers. We have been impressed by a relatively new tool from the development team at r2c called Semgrep. It’s a fast, open-source, static analysis tool for finding bugs and enforcing code standards. Semgrep’s rules look like the code you are searching for; this means you can write your own rules without having to understand abstract syntax trees (ASTs) or wrestle with regexes.
Semgrep’s flexible rule syntax is ideal for streamlining GitLab’s Custom Rulesets feature for extending and modifying detection rules, a popular request from GitLab SAST customers. Semgrep also has a growing open-source registry of 1,000+ community rules.
We are in the process of transitioning many of our lint-based SAST analyzers to Semgrep. This transition will help increase stability, performance, rule coverage, and allow GitLab customers access to Semgrep’s community rules and additional custom ruleset capabilities that we will be adding in the future. We have enjoyed working with the r2c team and we cannot wait to transition more of our analyzers to Semgrep. You can read more in our transition epic, or try out our first experimental Semgrep analyzers for JavaScript, TypeScript, and Python.
We are excited about what this transition means for the future of GitLab SAST and the larger Semgrep community. GitLab will be contributing to the Semgrep open-source project including additional rules to ensure coverage matches or exceeds our existing analyzers."
"GitLab SAST historically has been powered by over a dozen open-source static analysis security analyzers. These analyzers have proactively identified millions of vulnerabilities for developers using GitLab every month. Each of these analyzers is language-specific and has different technology approaches to scanning. These differences produce overhead for updating, managing, and maintaining additional features we build on top of these tools, and they create confusion for anyone attempting to debug.
The GitLab Static Analysis team is continuously evaluating new security analyzers. We have been impressed by a relatively new tool from the development team at r2c called Semgrep. It’s a fast, open-source, static analysis tool for finding bugs and enforcing code standards. Semgrep’s rules look like the code you are searching for; this means you can write your own rules without having to understand abstract syntax trees (ASTs) or wrestle with regexes.
Semgrep’s flexible rule syntax is ideal for streamlining GitLab’s Custom Rulesets feature for extending and modifying detection rules, a popular request from GitLab SAST customers. Semgrep also has a growing open-source registry of 1,000+ community rules.
We are in the process of transitioning many of our lint-based SAST analyzers to Semgrep. This transition will help increase stability, performance, rule coverage, and allow GitLab customers access to Semgrep’s community rules and additional custom ruleset capabilities that we will be adding in the future. We have enjoyed working with the r2c team and we cannot wait to transition more of our analyzers to Semgrep. You can read more in our transition epic, or try out our first experimental Semgrep analyzers for JavaScript, TypeScript, and Python.
We are excited about what this transition means for the future of GitLab SAST and the larger Semgrep community. GitLab will be contributing to the Semgrep open-source project including additional rules to ensure coverage matches or exceeds our existing analyzers."
I'd be careful with how much of a warm fuzzy the tool gives you. See this example from my other comment in the thread: https://news.ycombinator.com/item?id=26905880 If it were really looking at AST level data, that wouldn't have fooled it.
I suspect there would be similar issues with your example of ensuring no use of eval() in PHP. So it seems okay to keep your own developers informed, but I wouldn't use it, alone, to vet outside code. PHP has eval-like functionality buried in preg_replace(), assert(), and probably other places. This tool also doesn't seem to dig into namespaced "aliases".
I suspect there would be similar issues with your example of ensuring no use of eval() in PHP. So it seems okay to keep your own developers informed, but I wouldn't use it, alone, to vet outside code. PHP has eval-like functionality buried in preg_replace(), assert(), and probably other places. This tool also doesn't seem to dig into namespaced "aliases".
> If it were really looking at AST level data, that wouldn't have fooled it.
Semgrep does look at an AST; but that counterexample is not something you can "fix" solely by looking at an AST. You need actual Python-specific semantic analysis that knows that all "open" functions like 'print' come from the builtins module, and thus are bound to the same identifier. They're literally built into the implementation, it's not something you can "discover" from analyzing existing Python source. Even if you had a perfectly accurate python AST it couldn't "tell" you this fact, it's a priori knowledge, and all analysis engines need a base set of facts like this that they work from.
> but I wouldn't use it, alone, to vet outside code.
I mean, nobody seems to be suggesting this though, and the OP quite literally stated the major value of the tool is enforcing domain/codebase-specific rules among a team. Which is a really good use for it! There are tons of little useful patterns you can codify this way.
Semgrep does look at an AST; but that counterexample is not something you can "fix" solely by looking at an AST. You need actual Python-specific semantic analysis that knows that all "open" functions like 'print' come from the builtins module, and thus are bound to the same identifier. They're literally built into the implementation, it's not something you can "discover" from analyzing existing Python source. Even if you had a perfectly accurate python AST it couldn't "tell" you this fact, it's a priori knowledge, and all analysis engines need a base set of facts like this that they work from.
> but I wouldn't use it, alone, to vet outside code.
I mean, nobody seems to be suggesting this though, and the OP quite literally stated the major value of the tool is enforcing domain/codebase-specific rules among a team. Which is a really good use for it! There are tons of little useful patterns you can codify this way.
>Semgrep does look at an AST; but that counterexample is not something you can "fix" solely by looking at an AST
Perhaps I worded it poorly. Dumping the python AST for builtins.print() makes it pretty clear that it's "print" though. So I'm curious why that skirts the rule.
>I mean, nobody seems to be suggesting this though
Not specificially, but the context is using it for security purposes with phrases like "every use of a potentially injectable function such as exec,system,etc. in PHP". Felt like that was worth commenting on.
Perhaps I worded it poorly. Dumping the python AST for builtins.print() makes it pretty clear that it's "print" though. So I'm curious why that skirts the rule.
>I mean, nobody seems to be suggesting this though
Not specificially, but the context is using it for security purposes with phrases like "every use of a potentially injectable function such as exec,system,etc. in PHP". Felt like that was worth commenting on.
> Dumping the python AST for builtins.print() makes it pretty clear that it's "print" though.
No, the AST only tells you it's a method call on something called "builtins." You need the separate semantic knowledge of what builtins is in order to figure it out. Parsing + AST just means it sees "method call of `print` on `builtins` object". Regular print calls would come through as "regular function call of `print`".
No, the AST only tells you it's a method call on something called "builtins." You need the separate semantic knowledge of what builtins is in order to figure it out. Parsing + AST just means it sees "method call of `print` on `builtins` object". Regular print calls would come through as "regular function call of `print`".
> Perhaps I worded it poorly. Dumping the python AST for builtins.print() makes it pretty clear that it's "print" though. So I'm curious why that skirts the rule.
To echo the other replies, the AST for builtins.print() is the same as the ast for mymodule.print() and, in fact, if you stick a builtins.py in the right place, you'll be able to prevent the import of the standard library builtin module, while the ast's would be identical.
To echo the other replies, the AST for builtins.print() is the same as the ast for mymodule.print() and, in fact, if you stick a builtins.py in the right place, you'll be able to prevent the import of the standard library builtin module, while the ast's would be identical.
[deleted]
I'm honestly surprised we haven't seen complete democratization of linting/grepping/refactoring tools. Imagine being able to script a one-off refactor you want to make that's too project-specific to be included in the IDE itself.
Writing the parser is nontrivial, but once you have it it should be straightforward to expose a programmatic API for doing this stuff instead of trying to hardcode every useful linter rule into a single program.
Writing the parser is nontrivial, but once you have it it should be straightforward to expose a programmatic API for doing this stuff instead of trying to hardcode every useful linter rule into a single program.
You can do this with Rust using a combination of rustc, syn and a build.rs file. Then you can execute more Rust code on the parsed AST.
In the JVM world annotation processors or compiler plugins can have access to the AST during compilation. Both in Kotlin and Java.
In the JVM world annotation processors or compiler plugins can have access to the AST during compilation. Both in Kotlin and Java.
We do this with rubocop and its ability to parse the ruby AST. The API to actually write rules in rubocop is not particularly the best, but it has been highly successful in codebase and domain-specific ruby linting and autofixing.
Writing a parser for one specific version of a language is one thing (nontrivial), but writing a parser than parsed most versions of most programming languages and keeping it up-to-date is a enormous undertaking and cannot be done by one person
For C/C++ code, you can already do refactoring using clang-tidy scripts [0], or even can write custom linters using libtooling [1] and leverage the AST Matchers [2] which work at the AST level.
All that's needed is a compile_commands.json file which can be easily generated via most build systems, or you can use Bear [3]/some other tool (or write a script that logs all syscalls and generate it yourself).
[0] https://releases.llvm.org/12.0.0/tools/clang/tools/extra/doc...
[1] https://releases.llvm.org/12.0.0/tools/clang/docs/LibTooling...
[2] https://releases.llvm.org/12.0.0/tools/clang/docs/LibASTMatc...
[3] https://github.com/rizsotto/Bear
All that's needed is a compile_commands.json file which can be easily generated via most build systems, or you can use Bear [3]/some other tool (or write a script that logs all syscalls and generate it yourself).
[0] https://releases.llvm.org/12.0.0/tools/clang/tools/extra/doc...
[1] https://releases.llvm.org/12.0.0/tools/clang/docs/LibTooling...
[2] https://releases.llvm.org/12.0.0/tools/clang/docs/LibASTMatc...
[3] https://github.com/rizsotto/Bear
I wrote a small VS code extension and pre-commit hook that might meet 80% of your needs:
https://github.com/elanning/checkr
It is just simple regex at this time, but hopefully I can add something like CCGrep syntax in the future:
https://github.com/yuy-m/CCGrep
https://github.com/elanning/checkr
It is just simple regex at this time, but hopefully I can add something like CCGrep syntax in the future:
https://github.com/yuy-m/CCGrep
Isn't a problem here that, since there's no simple definition of what it's doing, there's no simple way to assess your false negative rate when searching for something? That is fine for many pragmatic informal uses but doesn't seem a good fit for security purposes.
Python you can probably do that just from the standard library. ast.parse and all that.
Perhaps, but this tool has a syntax and common interface for multiple languages. This is a huge resource for IT/security. I could imagine this being a helpful refactoring tool as well for CLI.
No need to overstate. It's fine, but the rules seem to need to be very bespoke, and any language's parser will do a better job of figuring out syntax.
The name "Semantic Grep" does not give a good idea for what this tool is and what it does.
The web page states: "Static analysis at ludicrous speed. Find bugs and enforce code standards"
"grep" is short for "global regular expression print". It finds matches for the given regular expression and prints them.
"Semantic Grep" is a static analyzer with configurable rules, style checks, etc. It does much more than search and print.
Perhaps a better name is needed?
Edit: How about "omnilint" or "omnicritic" since semgrep is more of a "lint" (https://en.wikipedia.org/wiki/Lint_(software)) or "critic" (https://en.wikipedia.org/wiki/Perl::Critic) type of tool that handles multiple languages?
Edit2: "Static analysis at ludicrous speed" ==> "turbolint"? ("ludicrous speed" reminds of the hilarious Space Balls scene :) "turbolint, GO!"
The web page states: "Static analysis at ludicrous speed. Find bugs and enforce code standards"
"grep" is short for "global regular expression print". It finds matches for the given regular expression and prints them.
"Semantic Grep" is a static analyzer with configurable rules, style checks, etc. It does much more than search and print.
Perhaps a better name is needed?
Edit: How about "omnilint" or "omnicritic" since semgrep is more of a "lint" (https://en.wikipedia.org/wiki/Lint_(software)) or "critic" (https://en.wikipedia.org/wiki/Perl::Critic) type of tool that handles multiple languages?
Edit2: "Static analysis at ludicrous speed" ==> "turbolint"? ("ludicrous speed" reminds of the hilarious Space Balls scene :) "turbolint, GO!"
I clicked on this thinking it's a grep that can search code snippets based on language-aware syntax matching instead of regular expressions.
Agreed, this project name is misleading about what it does. The name "grep" always indicated some kind of "find a text/pattern and print results to stdout" utility. Like pgrep, which searches running processes by name and then prints their IDs.
Agreed, this project name is misleading about what it does. The name "grep" always indicated some kind of "find a text/pattern and print results to stdout" utility. Like pgrep, which searches running processes by name and then prints their IDs.
> it's a grep that can search code snippets based on language-aware syntax matching instead of regular expressions.
Hey, I'm a maintainer of Semgrep, and this sounds like a pretty good description of what the CLI can do, see this example for finding all function/class/method calls:
Hey, I'm a maintainer of Semgrep, and this sounds like a pretty good description of what the CLI can do, see this example for finding all function/class/method calls:
$ semgrep -e '$NAME(...)' -l python
flask_todomvc/extensions.py
4:db = SQLAlchemy()
------------------------------------------------------------
5:security = Security()
flask_todomvc/factory.py
15: app = Flask(__name__)
------------------------------------------------------------
17: app.config.from_object(settings)
------------------------------------------------------------
18: app.config.from_envvar('TODO_SETTINGS', silent=True)Oh, that's great to see. The website's presentation made a different impression with its "enforce code standards" angle.
Looks like a pretty useful tool with a couple nice options. A bit strange that the `-e` option is only explained on the website, but to be fair it seems to be a lot to cover. Still, a kind of "cheat sheet" style summary in the help message would be fantastic, just as a little suggestion.
Looks like a pretty useful tool with a couple nice options. A bit strange that the `-e` option is only explained on the website, but to be fair it seems to be a lot to cover. Still, a kind of "cheat sheet" style summary in the help message would be fantastic, just as a little suggestion.
question, you mention "no more AST parsing" as a selling line for semgrep. Isn't this actually a bad thing for a staric analyzer, as ASTs are actually... abstract, and closer to the real logic of what the code does? I know analyzing text is faster but is it worth?
The tool abstracts away the AST with a more intuitive, human friendly interface. Similarly to how Regular Expressions do for strings matching logic
I think the name's just fine. It searches through your code in a way that you can define semantically/with more context. All of the alternatives you mention carry less meaning, and are less memorable.
This is like saying that PubNub is a bad name because it does messaging, and has little to do with pub-sub. Or hell, even that Y Combinator should be called something like StartupFactory since it's not really a recursive tool.
In short, the metaphor's close enough.
This is like saying that PubNub is a bad name because it does messaging, and has little to do with pub-sub. Or hell, even that Y Combinator should be called something like StartupFactory since it's not really a recursive tool.
In short, the metaphor's close enough.
The literal meaning of "grep" is not the only meaning. It also means “find snippet in files.”
Yes.
But at least to me, semgrep looks a lot more like "lint" than "grep".
But at least to me, semgrep looks a lot more like "lint" than "grep".
You have to find stuff before you lint it.
There is the common, if informal, definition that grep means "command line text search tool". I read this as "semantic/syntax search tool".
But semgrep is much closer to a linter / critic program than a grep program.
[deleted]
Is there a more complete example of how to call semgrep from pre-commit (which gets called before every git commit) in order to prevent e.g. Python print calls (print(), print \\n(), etc.) from being checked in?
https://semgrep.dev/docs/extensions/ describes how to do pre-commit.
Nvm, here's semgrep's own .pre-commit-config.yml for semgrep itself: https://github.com/returntocorp/semgrep/blob/develop/.pre-co...
https://semgrep.dev/docs/extensions/ describes how to do pre-commit.
Nvm, here's semgrep's own .pre-commit-config.yml for semgrep itself: https://github.com/returntocorp/semgrep/blob/develop/.pre-co...
I've never used the `pre-commit` framework, but it's really simple to wire up arbitrary shell scripts; check out the
`.git/hooks` directory in your repo for samples, e.g. `.git/hooks/pre-commit.sample`.
You can run any old shell script there, without having to install a python tool.
`.git/hooks` directory in your repo for samples, e.g. `.git/hooks/pre-commit.sample`.
You can run any old shell script there, without having to install a python tool.
Yeah but that githook will only be installed on that one repo on that one machine. And they may have no or a different version of bash installed (on e.g. MacOS or Windows). IMHO, POSIX-compatible portable shell scripts are more trouble than portable Python scripts.
Pre-commit requires Python and pre-commit to be installed (and then it downloads every hook function).
This fetches the latest version of every hook defined in the .pre-commit-config.yml:
A person could easily `ln -s repo/.hooks/hook*.sh repo/.git/hooks/` after every git clone.
Pre-commit requires Python and pre-commit to be installed (and then it downloads every hook function).
This fetches the latest version of every hook defined in the .pre-commit-config.yml:
pre-commit autoupdate
https://pre-commit.com/#pre-commit-autoupdateA person could easily `ln -s repo/.hooks/hook*.sh repo/.git/hooks/` after every git clone.
Out of curiosity, Is there value in doing this over (say) running a GitHub Action post commit and failing the build if it finds something nasty?
If you can catch it before the commit is even made then why do/wait for a build?
Fair enough. Guess IDE plugins work even better for that
IDE plugins are not at all consistent from one IDE to another. Pre-commit is great for teams with different IDEs because all everyone needs to do is:
[pip,] install pre-commit
pre-commit install
# git commit
# pre-commit run --all-files
# pre-commit autoupdate
https://pre-commit.com/Since the capability has never existed, I don't think in terms of being able to semgrep. If that makes any sense. My brain is not wired this way, yet.
Like, if you've never tasted lychee, it would never occur to you how to cook with it.
I'm going to need to see some useful, real-world examples to jumpstart my brain to think this way.
Like, if you've never tasted lychee, it would never occur to you how to cook with it.
I'm going to need to see some useful, real-world examples to jumpstart my brain to think this way.
Hey, I work on Semgrep. As a real world example, I just noticed today that Hashicorp uses a whole bunch of Semgrep rules on terraform-provider-aws[0]. I'd recommend reading the `message` keys to know what they intend to match, and then the `patterns` lists below to see how that's accomplished.
Alternatively, we curate 1000+ community rules that you can look through as well.[1]
[0]: https://github.com/hashicorp/terraform-provider-aws/blob/mai...
[1]: https://semgrep.dev/r
Alternatively, we curate 1000+ community rules that you can look through as well.[1]
[0]: https://github.com/hashicorp/terraform-provider-aws/blob/mai...
[1]: https://semgrep.dev/r
Nice! Thanks. This will certainly help me start to thinking in semantic grep. I can see this being an additional coverage tool and am eager to study it.
You can cook with lychee?
There's lots of confusion about what semgrep does here, which is kind of unfortunate. I haven't touched it much, but I have built a very similar tool (I'm one of the contributors to refex[1], which is a very similar project).
The starting point of semantic grep is very useful. When you have a big codebase, you often want to detect antipatterns, or not even antipatterns, but just uses of a thing, say you're renaming a method and want to track down the callers.
Being able to act on the AST, instead of hoping you searched up all of the variants of whitespace and line breaks and, depending on the specific example, different uses of argument passing, is really useful.
But often when you're semantically grepping, your goal is to replace something with something else (this is what refex was initially built for: to aide in large scale changes in python, as a sort of equivalent to the C++ tools that Google uses).
But then you want to shift left even further: once you have a pattern that you want to replace once, you can just enforce that a linter yell at you when anyone does it again. So it's very natural to develop a linter-style thing on top of one of these[2].
This is, as I understand it sort of the same thing that happens in C++: clang-tidy and clang-format are written on top of AST libraries that can be used for ad-hoc analysis and transformations, but you can also just plug them into a linter.
The thing is, for most organizations, enforcing code style and best practices is more valuable than apply a refactoring to 10M lines of code, because most organizations don't have 10M lines of code to refactor. That doesn't mean that these tools aren't also useful for ad-hoc transforms and exploratory analysis. They absolutely are!
[1]: https://github.com/ssbr/refex
[2]: https://github.com/ssbr/refex/tree/main/refex/fix
The starting point of semantic grep is very useful. When you have a big codebase, you often want to detect antipatterns, or not even antipatterns, but just uses of a thing, say you're renaming a method and want to track down the callers.
Being able to act on the AST, instead of hoping you searched up all of the variants of whitespace and line breaks and, depending on the specific example, different uses of argument passing, is really useful.
But often when you're semantically grepping, your goal is to replace something with something else (this is what refex was initially built for: to aide in large scale changes in python, as a sort of equivalent to the C++ tools that Google uses).
But then you want to shift left even further: once you have a pattern that you want to replace once, you can just enforce that a linter yell at you when anyone does it again. So it's very natural to develop a linter-style thing on top of one of these[2].
This is, as I understand it sort of the same thing that happens in C++: clang-tidy and clang-format are written on top of AST libraries that can be used for ad-hoc analysis and transformations, but you can also just plug them into a linter.
The thing is, for most organizations, enforcing code style and best practices is more valuable than apply a refactoring to 10M lines of code, because most organizations don't have 10M lines of code to refactor. That doesn't mean that these tools aren't also useful for ad-hoc transforms and exploratory analysis. They absolutely are!
[1]: https://github.com/ssbr/refex
[2]: https://github.com/ssbr/refex/tree/main/refex/fix
> You need to enable JavaScript to run this app.
Wait, is this a web app? I was expecting a command line tool to navigate my code locally.
Wait, is this a web app? I was expecting a command line tool to navigate my code locally.
The cli is here: https://semgrep.dev/docs/getting-started/
You can write stuff like
You can write stuff like
# Check for Python == where the left and right hand sides are the same (often a bug)
$ semgrep -e '$X == $X' --lang=py path/to/srcCool! But this example is a bit simplistic since it can be done just as easily by regular grep:
grep -E '(.+) = \1' *.py
I have trouble looking at the examples in the project website (many things inside iframes are adblocked). Do you have any example of a search that would be difficult or impossible with grep?Your example matches the _text_, semgrep matches _the language_
given:
given:
if 1 \
== \
1:
pass
then $ semgrep -e '$X == $X' -l python
1:if 1 \
2: == \
3: 1:
ran 1 rules on 1 files: 1 findings
to follow myself up, one can also check for expressions like what I used as an example and say "don't do that", but without regard to what is inside the if semgrep -e $'if ...:\n pass\n' -l pythonIt can infer (x==y) if x=1 and y=1, which is grep cannot do.
This must surely fail... isn't it equivalent to solving the halting problem? Or does it run the whole program like a debugger?
If you're that capable with grep, surely you've run into it's shortcomings and can appreciate attempts to improve the status quo. Like trying to find usages of a variable that is a substring of a word. Like trying to fix code where somebody else has used the variable name i. Sure, you can add matching on word boundaries, but then it starts to become a distraction from the original task at hand.
There’s a demo on the site, I assume that’s it?
No, it's just the landing page. Apparently it does not allow to see it without running some javascript.
Well the demo is there on the landing page
[deleted]
When tools like this use terms like "legacy languages", and don't show that C is supported unless you click "More Languages", it makes me feel old. :)
Still, it seems rather cool, I like the idea of being able to search code at a higher level than just raw source text.
Still, it seems rather cool, I like the idea of being able to search code at a higher level than just raw source text.
Typo in the "Trying Semgrep" screenshot ("ruleste"): https://semgrep.dev/static/media/Step1.df848497.png
Isn't "grep for code" called just "grep"?
Semgrep started off as a “syntactic grep” but has increasingly become more semantic. So if you want to find all calls to foo that have 1 as the first argument, you just search for foo(1) and even things like x = 1; foo(x); will match.
Here’s an elaborate example: https://semgrep.dev/s/ievans:c-dataflow
Here’s an elaborate example: https://semgrep.dev/s/ievans:c-dataflow
It does seem potentially good for enforcing standards where the participants are willing. But you can work around it fairly easily. Like the example "python no-prints" rule: https://semgrep.dev/s/sabihb:no-prints
Lots of workarounds it wouldn't find, like:
Lots of workarounds it wouldn't find, like:
import builtins
builtins.print("whee")I'm guessing the value with the rules system is, you can add new rules easily. So during a code review, if you see somebody using your example, you could create a new rule to catch that.
I don't think you can go in with the mindset that it will catch everything, but rather, it's about being able to iterate quickly with your rules.
I don't think you can go in with the mindset that it will catch everything, but rather, it's about being able to iterate quickly with your rules.
Sure. I raised it because it keeps using the word "static analysis", which at least wouldn't be fooled by builtins.print(). It's more than grep, for sure, but something less than static analysis tools I've used. And I don't mean that as a knock. It's working across a lot of languages, so I see the tradeoff.
Ok, I've put the word 'semantic' up there so we can not get hung up on title stuff. (Submitted title said "Like Grep but for Code".)
That's called "a code walker", isn't it?
What does this give you over writing a flake8 plugin (for Python at least)?
I've found the flake8 API and documentation lacking, so perhaps just a cleaner interface?
I've found the flake8 API and documentation lacking, so perhaps just a cleaner interface?
Looks like a useful tool for me and I would like to try it.
Go down, see "brew install semgrep" and try to copy paste it. And it's an image :(
Go down, see "brew install semgrep" and try to copy paste it. And it's an image :(
There is also a bug in the example rules single pages app.
Go to https://semgrep.dev/p/jwt
Go to the page 2/5
Click "Run Locally", so you can copy the code
close the modal -> you're on page 1/5. Expectation would be to stay on page 2/5.
It would also be very useful to be able to filter by language and topic.
Go to https://semgrep.dev/p/jwt
Go to the page 2/5
Click "Run Locally", so you can copy the code
close the modal -> you're on page 1/5. Expectation would be to stay on page 2/5.
It would also be very useful to be able to filter by language and topic.
I currently use a highly opinionated ESLint config (based on the airbnb one) together with strict checking in my TypeScript config, and it is configured to run on every commit with husky git hooks. The example given on the Semgrep homepage is an exact match to one that exists in my ESLint config (eslint's no-console rule).
How does Semgrep compare to ESLint+a strict tsconfig?
How does Semgrep compare to ESLint+a strict tsconfig?
It seems from reading the docs that the “semantic” side is important here. It can track things like redefinitions.
E.g. const output = console.log; output(“hello”);
This wouldn’t be caught by ESLint (to my knowledge) but would be caught by Semgrep. I think you could do it with ESLint but given the interface for an ESLint plugin exposes an AST, you’d have to track this yourself. I’m assuming Semgrep could stretch to things like enforcing APIs are called with certain optional arguments present (even if the TS types don’t require it). Again, I think with ESLint you’d have to do more juggling with the raw AST.
That said, this is my understanding from a quick skim!
E.g. const output = console.log; output(“hello”);
This wouldn’t be caught by ESLint (to my knowledge) but would be caught by Semgrep. I think you could do it with ESLint but given the interface for an ESLint plugin exposes an AST, you’d have to track this yourself. I’m assuming Semgrep could stretch to things like enforcing APIs are called with certain optional arguments present (even if the TS types don’t require it). Again, I think with ESLint you’d have to do more juggling with the raw AST.
That said, this is my understanding from a quick skim!
How do you deal with false positives?
If the commit hook rejects anything where rules are triggered, a way to force the comrit is needed for the cases when the rule finding is not reanny an issue.
Upd: I found that the --no-verify option can be used in many cases
If the commit hook rejects anything where rules are triggered, a way to force the comrit is needed for the cases when the rule finding is not reanny an issue.
Upd: I found that the --no-verify option can be used in many cases
You can put comments in the code to ignore eslint rules on a specific line, or for the whole file.
I want the ease of use of their AST specification with the power of clang’s refactor tool. Has anyone attempted to do that?
Does it come with a standard set of rules that finds bad code without any false positives out of the box? Or is it more of a tool for people doing code security audits & pentesting who know what they are looking for and want to read the surrounding code?
No Windows support yet: https://github.com/returntocorp/semgrep/issues/1330
From the thread you link it looks like they're getting close, there's been activity in the past few days.
(I'm guessing from your comment that this is important to you (i.e. WSL/Docker is not a solution).)
(I'm guessing from your comment that this is important to you (i.e. WSL/Docker is not a solution).)
Kind of crazy that you can make a tool like this in the modern age that isn't cross platform. Maybe they just can't face the Python packaging nightmare on Windows.
Also kind of surprising it's written in Python given that they advertise its speed.
Also kind of surprising it's written in Python given that they advertise its speed.
I was surprised by this too, but as a maintainer of the project we’ve had comparatively little Windows requests compared to other systems. Qualitatively, for the folks who have asked for Windows support, WSL has been a viable option and reduced the support surface area for the small team behind the tool.
On the speed front, the core of Semgrep is OCaml, with a Python wrapper to add niceties like pattern composition. I’m less close to that part of the codebase, but think more and more logic is being moved to OCaml for performance reasons.
On the speed front, the core of Semgrep is OCaml, with a Python wrapper to add niceties like pattern composition. I’m less close to that part of the codebase, but think more and more logic is being moved to OCaml for performance reasons.
I’m always surprised at stuff I take for granted that doesn’t work on Windows. So yeah, it seems like cross-platform should be easy but since my dev environment is zsh, it’s easy for my stuff to work sort of “everywhere but Windows.”
Add to that that the reason things fail on Windows is usually something Windows specific and “their fault.” So it’s unusual for me to fire up a Windows VM just to sanity check my code. And since Windows CI runners cost 2x or more, I don’t usually run cross platform CI.
Add to that that the reason things fail on Windows is usually something Windows specific and “their fault.” So it’s unusual for me to fire up a Windows VM just to sanity check my code. And since Windows CI runners cost 2x or more, I don’t usually run cross platform CI.
This is an open source project on Github. They can use Github Actions which has free runners for Windows, Mac and Linux.
Windows runners consume 2x minutes, Mac runners consume 10x minutes [0].
Free projects only get 2,000 minutes per month so running on all three platforms means you only get 1/13th of the minutes of only using Linux.
I rarely use anything but Linux runners even on my paid projects. I like saving money, so unless I really need integration testing on Windows or Mac, I don’t do it.
[0] https://docs.github.com/en/github/setting-up-and-managing-bi...
Free projects only get 2,000 minutes per month so running on all three platforms means you only get 1/13th of the minutes of only using Linux.
I rarely use anything but Linux runners even on my paid projects. I like saving money, so unless I really need integration testing on Windows or Mac, I don’t do it.
[0] https://docs.github.com/en/github/setting-up-and-managing-bi...
The 2000 minute limit only applies to private projects.
How much does the CI service cost? I can't seem to find any information about it on the website without creating an account.
The CI service is free, with some limitations on how long the findings stay on the dashboard, SSO integration and maybe a few others. The paid version was $40/usr/mo the last time I checked
Once we figured it out, it takes us a few minutes to onboard a new repo to Semgrep
The underlying package tree-sitter that semgrep uses is pretty amazing too. It’s an incremental parser for many different languages written in C.
It blows my mind how fast it is compared to many tools in js ecosystem. Tree-sitter was parsing millions of files in half a minute. JS, TS, Ruby, yaml, html, Css. It’s quite magical. Such great engineering.
It blows my mind how fast it is compared to many tools in js ecosystem. Tree-sitter was parsing millions of files in half a minute. JS, TS, Ruby, yaml, html, Css. It’s quite magical. Such great engineering.
Interesting. Looks similar to Comby: https://comby.dev/ "a tool for searching and changing code structure". Comby is more on rewriting, it has less integration for a CI (though you can do it), it is less geared towards reporting.
Apparently this is invalid TypeScript (cannot parse it says):
try {
const parsedURL = new URL(url)
requestPath = parsedURL.pathname
} catch (error: unknown) {
// NOOP
}
It's complaining about : unknown bit which one of the newer typescript eslint rules enforces.Apparently
import random
if random.randint(0,1) == 2:
print(“hello”)
Is also unparseable.is that due to the smartquotes, or that's just an artifact of your HN comment?
Perhaps a more pointed set of questions: what is the error it emits, and have you considered submitting that case as an actual bug?
Perhaps a more pointed set of questions: what is the error it emits, and have you considered submitting that case as an actual bug?
Hi, this is very cool. I have been building up a suite of tools to roll out across major open source projects to improve security. I like what I have seen so far, this is a great use case. Whom can I connect with to learn more? And similarity/diff with sourcegraph, also like a lot.
Just the tool that I was looking for. We are looking to do Service linting in our organization as a method of making sure our services don't drift too far apart.
Anyone else know of a Service linting tool? OPA/conftest come close but lack syntax parsers for Ruby/Javascript.
Anyone else know of a Service linting tool? OPA/conftest come close but lack syntax parsers for Ruby/Javascript.
I used to use SAST-SCAN but that seems abandonware. I like that this exists. Everyone should go from nothing to something in the SAST space. A free/freemium tool/service for that is pretty great. The first couple runs have found useful results.
No swift support yet. What would be involved in adding it?
https://github.com/returntocorp/ocaml-tree-sitter/blob/maste... appears to be the general answer to your question, but navigating to the tree-sitter docs shows that tree-sitter has one in progress: https://github.com/tree-sitter/tree-sitter-swift so hopefully the machinery to incorporate it into semgrep will not be horrific
probably doing something wrong but running the ci ruleset on a tiny django hobby project made all cores spin at 100% after 33% of the progress bar and made the OS almost unresponsive. ctrl-c after 5 minutes and i still had to pkill every semgrep process... never seen the M1 airbook overheat this much before.
Semgrep maintainer here. We just ordered our first M1 laptop and will debug. Thanks for the bug report
Nice looking tool.
Is there a way to search for functions in C (other than printf!) whose return value is ignored at the call site?
Is there a way to search for functions in C (other than printf!) whose return value is ignored at the call site?
Really outstanding those guardrails rules from semgrep. Useful to enforce code. Thanks for sharing the tool.
Whenever I see "at ludicrous speed" or something to that effect, I now assume it's slow.
I click on the link above and I get a seemingly blank page, all because the website uses some JavaScript garbage and violates W3C standards. That's the ridiculous, disgusting state of the information technology industry in the 21st century. I rue the day I decided to do this professionally, and I am deeply ashamed and despondent.
How does this compare to the tools available at large companies like Google and Facebook?
[deleted]
For example, a webapp may have been designed such that authorisation needs to be explicitly added with a line or two to each controller. A semgrep rule can be written to match all the controllers which are missing this line. Then these controllers can be manually reviewed to assess whether unauthorised access should be allowed. Depending on what you are trying to match, this is something that may be very complex or even impossible to implement accurately in plain grep. Some languages like Ruby have powerful static analysis tools (Brakeman) that can also do this, but the benefit of Semgrep is the flexibility across multiple languages and how readable the rulesets are. [1]
[1] https://blog.includesecurity.com/2021/01/custom-static-analy...