GithubHelp home page GithubHelp logo

owasp / www-project-csrfguard Goto Github PK

View Code? Open in Web Editor NEW
69.0 14.0 37.0 3.74 MB

The aim of this project is to protect Java applications against CSRF attacks with the use of Synchronizer Tokens

Home Page: https://owasp.org/www-project-csrfguard/

License: BSD 3-Clause "New" or "Revised" License

Java 89.68% HTML 3.53% JavaScript 6.78% Ruby 0.02%
owasp csrf csrf-protection security security-tools hacktoberfest java maven

www-project-csrfguard's Introduction

License GitHub release Maven Central release OWASP Flagship Java CI OWASP Dependency check Snyk Security Analysis

Overview

Welcome to the home of the OWASP CSRFGuard Project! OWASP CSRFGuard is a library that implements a variant of the synchronizer token pattern to mitigate the risk of Cross-Site Request Forgery (CSRF) attacks. The OWASP CSRFGuard library is integrated through the use of a JavaEE Filter and exposes various automated and manual ways to integrate per-session or pseudo-per-request tokens into HTML. When a user interacts with this HTML, CSRF prevention tokens (i.e. cryptographically random synchronizer tokens) are submitted with the corresponding HTTP request. It is the responsibility of OWASP CSRFGuard to ensure the token is present and is valid for the current HTTP request. Any attempt to submit a request to a protected resource without the correct corresponding token is viewed as a CSRF attack in progress and is discarded. Prior to discarding the request, CSRFGuard can be configured to take one or more actions such as logging aspects of the request and redirecting the user to a landing page. The latest release enhances this strategy to support the optional verification of HTTP requests submitted using Ajax as well as the optional verification of referrer headers.

Project Leads

The CSRFGuard project is run by Azzeddine RAMRAMI and Istvan ALBERT-TOTH.

Using with Maven

Add the following dependencies to your Maven POM file to use the library:
Note: for the Jakarta releases use the -jakarta suffix in the version.

<dependency>
    <groupId>org.owasp</groupId>
    <artifactId>csrfguard</artifactId>
    <version>4.3.0</version>
</dependency>

<!-- Stateful web application support -->
<dependency>
	<groupId>org.owasp</groupId>
	<artifactId>csrfguard-extension-session</artifactId>
	<version>4.3.0</version>
</dependency>

<!-- JSP TAG support -->
<dependency>
	<groupId>org.owasp</groupId>
	<artifactId>csrfguard-jsp-tags</artifactId>
	<version>4.3.0</version>
</dependency>

Building the code

  1. Make sure you have Apache Maven 3.0.4+, JDK 1.8+ and respectively JDK 11+ for Jakarta installed
  2. Clone this repository locally
  3. Build the project by running mvn clean install in the project root directory
  4. Build and run the test JSP web application by running one of the following commands:
    mvn pre-integration-test -Pdeploy-jsp-webapp -pl csrfguard-test/csrfguard-test-jsp
    mvn -Pdeploy-jsp-webapp -pl csrfguard-test/csrfguard-test-jsp tomcat7:run
  5. Optional: you can use mvnDebug to enable remote debugging, then connect your IDE to it (default port is 8000)
  6. Use a web browser to access http://localhost:8080 to open the home page of the test project

Uploading to the Maven Central repository (for project leaders)

  1. Follow the Sonatype Open-Source Project Maven Repository Usage Guide to create a Sonatype user account;
  2. Next, open a support request to get your newly created username added to the Maven groupId org.owasp;
  3. The ticket must be approved by a CSRFGuard project leader or someone who already has permissions to deploy under the group and artifactId.
  4. Once the support request has been completed, follow the instructions in the Sonatype Maven repository usage guide mentioned above to upload new versions to the Maven Central repository.

GPG Key generation and distribution

See: https://central.sonatype.org/publish/requirements/gpg/

gpg --full-gen-key
gpg --list-keys
gpg --list-secret-keys # if you've migrated your keys from another machine, make sure you have your secret key(s) imported
gpg --keyserver keys.gnupg.net --send-key <your_public_key_here> # you can define other supported key servers as well

Example .m2/settings.xml snippet required for releasing:

<settings xmlns="https://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="https://maven.apache.org/SETTINGS/1.0.0
                      https://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>ossrh</id> <!-- the id must match with the repository id defined in distributionManagement -->
            <username><!--your_oss_sonatype_username--></username>
            <password><!--your_oss_sonatype_password--></password>
        </server>
    </servers>

    <profiles>
        <profile>
            <id>ossrh</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.passphrase><!--your_gpg_passphrase--></gpg.passphrase>
            </properties>
        </profile>
    </profiles>
</settings>

Test signing your artifacts manually:

mvn clean verify -Psign-artifacts -Dgpg.passphrase=<your_gpg_passphrase> # should generate .asc files in the target directory

Deploying to OSS Sonatype / Maven Central

Deploy a -SNAPSHOT version:

mvn clean deploy

Prepare a release:

mvn release:clean release:prepare
  1. Set the version number you want to release in <MAJOR.MINOR.PATCH> format (e.g. 4.0.0)
  2. Set the SCM release tag: (e.g. 4.0.0)
  3. Set the new development version (e.g. 4.0.1-SNAPSHOT)

Check the created commits and tag to make sure everything looks as expected:

git log
git show HEAD
git show HEAD^
git tag -l # list tags

Rollback the local release:

mvn release:rollback # or "git reset HEAD^^ --hard"
git tag -d <tag_name_to_delete>

Upload the release to OSS Sonatype (staging):

mvn release:perform 

The maven-release-plugin executes the deploy (default). This triggers the execution of the nexus-staging-maven-plugin, which uploads the artifacts to the OSS Sonatype staging repository and releases them if they meet the requirements.

Manual release of a staging repository (in case autoReleaseAfterClose is set to false)

  • Visit https://oss.sonatype.org/#stagingRepositories
  • Review the newly created repository against the requirements (JAR files, sources, JavaDocs and associated PGP armored ASCII files are present with the desired version etc.)
  • Close the repository to trigger the validation of the uploaded components
  • If there were no errors, click Release

Upon release, the new version is published to the Central Repository, typically within 30 minutes, but updates to search can take up to 4 hours.

Push the new release to GitHub:

git push origin master
git push origin <tag_name>

Maven repositories

You can download pre-compiled versions from:

CSRFGuard 4.0.0 Release Notes

www-project-csrfguard's People

Contributors

40rn05lyv avatar alexhatz05 avatar aramrami avatar ayomawdb avatar bpapez avatar cxzero avatar dependabot[bot] avatar forgedhallpass avatar glitchcube avatar hblankenship avatar hsn10 avatar ilsurih avatar itsallvoodoo avatar jellisgwn avatar krasnyanskiy avatar lav023 avatar martinmarsicano avatar matthajus avatar mmedjahed avatar owaspfoundation avatar primate-zero avatar renewolfert avatar skotfred avatar spoint42 avatar ssrijan avatar stefano-1973 avatar tsenovivan avatar venosov avatar vermava avatar yuri1969 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

www-project-csrfguard's Issues

Problem with : org.owasp.csrfguard.CsrfGuardServletContextListener ?

When i run my project using eclipse i have this error :

juil. 07, 2021 3:43:34 PM org.apache.catalina.core.StandardContext listenerStart
GRAVE: Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) org.owasp.csrfguard.CsrfGuardServletContextListener
java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
at org.owasp.csrfguard.CsrfGuardServletContextListener.contextInitialized(CsrfGuardServletContextListener.java:81)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1702)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)
... 10 more

pageTokenSynchronizationTolerance check looks wrong

I wanted to upgrade csrfguard from 3.1.0 to 4.1.1 in order to activate TokenPerPage in our application. We have a page, where on initialization three AJAX POST requests are sent to the same URL (with different Payload). Our automated test was failing after activating TokenPerPage. On debugging I found that the following method does not match the description:

* @return true if the page token creation is within the configured time tolerance and the application should also accept the master token for validation
*/
private boolean initIsWithinTimeTolerance(final CsrfGuard csrfGuard, final boolean isAjaxRequest, final PageTokenValue tokenTimedPageToken) {
return isAjaxRequest
&& !csrfGuard.isTokenPerPagePrecreate()
&& tokenTimedPageToken.getCreationTime().plus(this.csrfGuard.getPageTokenSynchronizationTolerance()).isBefore(LocalDateTime.now());
}

I think that isBefore should be replaced with isAfter. To return true the current time should be before the sum of token creation time and tolerance, but currently its exactly the opposite.

Printing the CsrfGuard's config leads to java.lang.reflect.InaccessibleObjectException in Java 17

First opened as discussion: in #178

Describe the bug
When using the print feature of the CsrfGuard, either by activating it in csrfguard.properties (org.owasp.csrfguard.Config.Print = true) or in web.xml (set context parameter "Owasp.CsrfGuard.Config.Print" to true), you get the following stacktrace, complaining that the "java.util.regex" package is not accessible via reflection:

java.lang.reflect.InaccessibleObjectException: Unable to make field static final boolean java.util.regex.Pattern.$assertionsDisabled accessible: module java.base does not "opens java.util.regex" to unnamed module @45ed3a9b
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
	at java.base/java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:130)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.appendFieldsIn(ReflectionToStringBuilder.java:645)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:840)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:313)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:166)
	at org.apache.commons.lang3.builder.RecursiveToStringStyle.appendDetail(RecursiveToStringStyle.java:73)
	at org.apache.commons.lang3.builder.ToStringStyle.appendInternal(ToStringStyle.java:579)
	at org.apache.commons.lang3.builder.ToStringStyle.append(ToStringStyle.java:466)
	at org.apache.commons.lang3.builder.ToStringBuilder.append(ToStringBuilder.java:860)
	at org.owasp.csrfguard.util.CsrfGuardPropertiesToStringBuilder.append(CsrfGuardPropertiesToStringBuilder.java:186)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.appendFieldsIn(ReflectionToStringBuilder.java:654)
	at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:840)
	at org.owasp.csrfguard.util.CsrfGuardPropertiesToStringBuilder.toString(CsrfGuardPropertiesToStringBuilder.java:68)
	at org.owasp.csrfguard.CsrfGuard.toString(CsrfGuard.java:281)
	at java.base/java.lang.String.valueOf(String.java:4218)
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:173)
	at org.owasp.csrfguard.CsrfGuardServletContextListener.printConfigIfConfigured(CsrfGuardServletContextListener.java:131)
	at org.owasp.csrfguard.servlet.JavaScriptServlet.init(JavaScriptServlet.java:155)
	...

Currently the only work-around is to not log the config. :-(

To Reproduce
Steps to reproduce the behavior:

  1. Enable printing the configuration via csrfguard.properties (org.owasp.csrfguard.Config.Print = true)
  2. Start the application
  3. See error

Expected behavior
Normal logging of the app, no stacktrace.

Additional context
I think the field "javascriptRefererPattern" of the org.owasp.csrfguard.config.PropertiesConfigurationProvider needs to be added to the "FIELDS_TO_EXCLUDE" constant array in org.owasp.csrfguard.util.CsrfGuardPropertiesToStringBuilder to prevent at least this error.

Probably other fields of the PropertiesConfigurationProvider are also affected, like "pageTokenSynchronizationTolerance" (java.time.Duration) or "prng" (java.security.SecureRandom).

Migrate and update documentation

In OWASP-CSRFGuard/csrfguard/src/main/resources/csrfguard.properties this link
https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection
is not valid. The page doesn't exists anymore and reditect to https://owasp.org/www-project-csrfguard/

May be at the moment can be substituted with https://wiki.owasp.org/index.php/CSRFGuard_3_Token_Injection (waiting for a 4.0 updated page)?

P.S.: the documentation to the usage of the 4.x library doesn't exists and also the old documentation of 3.1.0 has been removed (the page doesn't exist anymore using the old link http://www.owasp.org/index.php/CSRFGuard-3- Configuration). If someone want the old documentation it can be found here: https://wiki.owasp.org/index.php/CSRFGuard_3_User_Manual

Why csrfguard creates so many Tomcat sessions?

Why csrfguard creates so many Tomcat sessions?

The Tomcat application is configured with the legacy unique per-session model. After the application is started from Tomcat manager (https://localhost/manager/html), I open the application with the browser and open several jsp pages. Instantanly hundreds of sessions are created and they can see at Tomcat manager panel. Each session with only an attribute ARC_CSRFTOKEN and its value like this one as an example: UNVH-ICE1-N9Q2-9BU2-7GWQ-R250-OT93-QMYA

If I navigate the same pages with another web explorer, then no more session are created. It's like the sessions with the token attribute are shared between different users.

Is this the normal behaviour? My concern is that this could be an anormal session creation

Thanks in advance

Inaccurate Properties Printout

Describe the bug
The printout of my configurations is not completely accurate to what I have configured, specifically the JavaScriptServlet configs. Though the configurations are being respected during testing. Meaning that if I set injectGetForms to true this is working as intended; if I set it to false, that too works. I do not utilize configuring these within web.xml, everything is via the properties file in my app's WEB-INF folder.

To Reproduce
My test app is a Websphere app. Here is the config file I am using to test.
csrfguard.txt

Expected behavior
CSRFGuard 3.x printing is accurate.

Screenshots
Printing properties before JavaScript servlet, note, the JavaScript properties might not be initialized yet:
OWASP CSRFGuard properties


  • Actions:
    • org.owasp.csrfguard.action.Redirect
      • Parameter: Page = /CG4xWeb/error.html
    • org.owasp.csrfguard.action.Log
      • Parameter: Message = potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
  • Ajax: true
  • Enabled: true
  • Force Synchronous Ajax: false
  • Is Javascript Inject Into Dynamically Created Nodes: false
  • Javascript Domain Strict: false
  • Javascript Inject Form Attributes: false
  • Javascript Inject Get Forms: false
  • Javascript Inject Into Attributes: false
  • Javascript Inject Into Forms: false
  • Javascript Params Initialized: false
  • Javascript Referer Match Domain: false
  • Javascript Referer Match Protocol: false
  • Logical Session Extractor: org.owasp.csrfguard.session.SessionTokenKeyExtractor
  • New Token Landing Page: /CG4xWeb/home
  • Page Token Synchronization Tolerance: 2000 ms
  • Print Config: true
  • Prng: java.security.SecureRandom(algorithm: SHA1PRNG, provider: IBMJCE version 1.8)
  • Protect: false
  • Rotate: false
  • Token Holder: org.owasp.csrfguard.token.storage.impl.InMemoryTokenHolder
  • Token Length: 32
  • Token Name: OWASP-CSRFTOKEN
  • Token Per Page: false
  • Token Per Page Precreate: false
  • Unprotected Pages:
    • /CG4xWeb/static/*
    • /CG4xWeb/home
    • /CG4xWeb/error.html
    • /CG4xWeb/JavaScriptServlet
  • Use New Token Landing Page: true
  • Validation When No Session Exists: true

Printing properties after JavaScript servlet, note, the javascript properties have now been initialized:
OWASP CSRFGuard properties


  • Actions:
    • org.owasp.csrfguard.action.Redirect
      • Parameter: Page = /CG4xWeb/error.html
    • org.owasp.csrfguard.action.Log
      • Parameter: Message = potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
  • Ajax: true
  • Enabled: true
  • Force Synchronous Ajax: false
  • Is Javascript Inject Into Dynamically Created Nodes: false
  • Javascript Domain Strict: false
  • Javascript Inject Form Attributes: false
  • Javascript Inject Get Forms: false
  • Javascript Inject Into Attributes: false
  • Javascript Inject Into Forms: false
  • Javascript Params Initialized: false
  • Javascript Referer Match Domain: false
  • Javascript Referer Match Protocol: false
  • Logical Session Extractor: org.owasp.csrfguard.session.SessionTokenKeyExtractor
  • New Token Landing Page: /CG4xWeb/home
  • Page Token Synchronization Tolerance: 2000 ms
  • Print Config: true
  • Prng: java.security.SecureRandom(algorithm: SHA1PRNG, provider: IBMJCE version 1.8)
  • Protect: false
  • Rotate: false
  • Token Holder: org.owasp.csrfguard.token.storage.impl.InMemoryTokenHolder
  • Token Length: 32
  • Token Name: OWASP-CSRFTOKEN
  • Token Per Page: false
  • Token Per Page Precreate: false
  • Unprotected Pages:
    • /CG4xWeb/static/*
    • /CG4xWeb/home
    • /CG4xWeb/error.html
    • /CG4xWeb/JavaScriptServlet
  • Use New Token Landing Page: true
  • Validation When No Session Exists: true

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Edge
  • Version: 97.0.1072.69

add the code of conduct

Is your feature request related to a problem? Please describe.
There isn't any code of conduct file unlike att the other OWASP web repositories

Describe the solution you'd like
Add a CODE_OF_CONDUCT.md.

Describe alternatives you've considered
none

Additional context
I'd like to work on this issue so please assign me this.

NPE in case of un-exploded WAR deployments

In case of unexplore deployment , no file system is been created , thus when we try to read properties or csrfguard.js from using getRealPath() we are getting null. So instead of reading file using getRealPath() , we could read file from the context from path.

Steps to reproduce the behavior:

  1. In TomCat 9 (Tomcat9 -> conf-> server.xml).
  2. In server.xml search of unpackWARs and set unpackWARs to false.
  3. We can use any Example project , just add csrfguard.properties and csrfguard.js file inside web.xml file.
  4. create the war and try to deploy this war using above configuration in tomcat.
  5. Deployment will fail in this case , since it will not be able to read the file.

Expected behavior
We should be able to deploy the war and we should be able to get csrfguard.js file .

Desktop (please complete the following information):

  • OS: windows
  • Browser chrome
  • Version 101.0.4951.64

Pull request of this is #99 . And we had a discussion about this issue few weeks back #91 .
This issue is reproducible in older release also. Here is an example project with old jar(csrfguard-3.1.0.jar ).
Example.zip

NewTokenLandingPage not working

Describe the bug
NewTokenLandingPage still doesn't work in 4.x and did not work in 3.x. In 3.x, I remember it was the httpSession.isNew() check was always false. I haven't tested 4.x yet to see if it is still that or the csrfGuard.isUseNewTokenLandingPage() check.

The result is a redirect to my configured org.owasp.csrfguard.action.Redirect.Page

To Reproduce
Steps to reproduce the behavior:
Providing WebSphere test app source code.
CSRFGuard4 test.zip

Try hitting this URL, http://localhost/CG4xWeb/app?param1=foo at

Expected behavior
The /app endpoint is protected which should cause a redirect to /home which is my configured NewTokenLandingPage; as well as org.owasp.csrfguard.unprotected.Default.

Bad performance in serving the javascript

We wanted to release our product with upgrading csrfguard from version 3.1.0 to 4.1.2, however due to bad results in our performance test we could not do it (mean time of requests were up to 25% slower and the 99% line up to 80% slower).

Looking at the flight recorder dump the culprit seems to be this code

String code = csrfGuard.getJavascriptTemplateCode();
code = code.replace(TOKEN_NAME_IDENTIFIER, StringUtils.defaultString(csrfGuard.getTokenName()))
.replace(TOKEN_VALUE_IDENTIFIER, StringUtils.defaultString(getMasterToken(request, csrfGuard)))
.replace(UNPROTECTED_EXTENSIONS_IDENTIFIER, String.valueOf(csrfGuard.getJavascriptUnprotectedExtensions()))
.replace(CONTEXT_PATH_IDENTIFIER, StringUtils.defaultString(request.getContextPath()))
.replace(SERVLET_PATH_IDENTIFIER, StringUtils.defaultString(request.getContextPath() + request.getServletPath()))
.replace(X_REQUESTED_WITH_IDENTIFIER, StringUtils.defaultString(csrfGuard.getJavascriptXrequestedWith()))
.replace(DYNAMIC_NODE_CREATION_EVENT_NAME_IDENTIFIER, StringUtils.defaultString(csrfGuard.getJavascriptDynamicNodeCreationEventName()))
.replace(DOMAIN_ORIGIN_IDENTIFIER, ObjectUtils.defaultIfNull(csrfGuard.getDomainOrigin(), StringUtils.defaultString(parseDomain(request.getRequestURL()))))
.replace(INJECT_INTO_FORMS_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptInjectIntoForms()))
.replace(INJECT_GET_FORMS_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptInjectGetForms()))
.replace(INJECT_FORM_ATTRIBUTES_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptInjectFormAttributes()))
.replace(INJECT_INTO_ATTRIBUTES_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptInjectIntoAttributes()))
.replace(INJECT_INTO_DYNAMIC_NODES_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptInjectIntoDynamicallyCreatedNodes()))
.replace(INJECT_INTO_XHR_IDENTIFIER, Boolean.toString(csrfGuard.isAjaxEnabled()))
.replace(TOKENS_PER_PAGE_IDENTIFIER, Boolean.toString(csrfGuard.isTokenPerPageEnabled()))
.replace(DOMAIN_STRICT_IDENTIFIER, Boolean.toString(csrfGuard.isJavascriptDomainStrict()))
.replace(ASYNC_XHR, Boolean.toString(!csrfGuard.isForceSynchronousAjax()));

The problem is that this create many rather large String and StringBuilder objects. It would be much better to create one StringBuilder, then do all the replacements in it, and at the end create the String.

This code is called on every request (if TokenPerPage is enabled) or if we switch off the caching via configuration (see this discussion: #57)

I modified the code and ran the performance test again, and then the times were again similar to what we had with csrfguard 3.1.0. Actually that code was there already in 3.1.0, but with less variable placeholders, so it created less garbage than in version 4.

Lots of copied code from the Grouper repository

The following classes:

  • org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeBase (original source code)
  • org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeCommonUtils
  • org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeUtils

were copied from the Grouper repository.

It seems that only a few changes has been made:

  • Logging: although the code is commented out, so it's not relevant (org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeBase#iLogger)

  • Skipping the Expression Language (EL) related processing in org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeBase#propertiesHelper: again this is only relevant if there are keys with ".elConfig" suffix

  • The following lines of code:

    //InputStream inputStream = configFile.getConfigFileType().inputStream(configFile.getConfigFileTypeConfig(), this);
    try {
        //get the string and store it first (to see if it changes later)
        String configFileContents = configFile.retrieveContents(this);
        configFile.setContents(configFileContents);
        result.properties.load(new StringReader(configFileContents));

    in org.owasp.csrfguard.config.overlay.ConfigPropertiesCascadeBase#retrieveFromConfigFiles which seem to do the same as the original code.

The question is, are these modifications really needed? If not, the original code could be used as a maven dependency:

<dependency>
     <groupId>edu.internet2.middleware.grouper</groupId>
     <artifactId>grouper-activemq</artifactId>
     <version>2.5.29</version>
</dependency>

Side note: the Grouper project is outdated/bulky/poorly written with a lot of duplicated code from the org.apache.commons:commons-lang3 and other common libraries. It would be nice to replace with a better alternative

Removing execCommand from ConfigPropertiesCascadeCommonUtils

It seems like there is no practical usage of execCommand method available in [1]. Please correct me if I'm wrong here. It seems that the function is not used anywhere in the code.

If there is no use of it, I'd love to help cleaning up ConfigPropertiesCascadeCommonUtils. This can have unnecessary security complications since it's a public static method, and we have some commercial security scanners complaining about it already.

[1]

public static CommandResult execCommand(String[] arguments, boolean exceptionOnExitValueNeZero) {

Add Jakarta support

There is a new branch named jakarta created for this purpose, but the preferred solution would be to use some automated approach (e.g. Eclipse Transformer) that would do the required changes as a release step, hence removing the need for maintaining two almost identical branches.

Related discussions:

Documentation: csrfguard.properties improvement

The following text in csrfguard.properties could be cleaned up and more concise:

# Note: Rotation in case of AJAX requests is not currently not supported because of the possible race conditions.
# A Single Page Application can fire multiple simultaneous requests. If rotation is enabled,
# the first request might trigger a token change before the validation of the same token within the second request,
# causing false-positive CSRF intrusion exceptions.

"is not currently not supported"

The sentence starting "If rotation is enabled, ..." could be clearer, "If rotation were enabled for AJAX requests, the first request could trigger..."

Happy to provide a PR if it would be helpful.

CsrfGuard.regexpPatternCache is not thread safe

Describe the bug
CsrfValidator.isUriRegexMatch() is not thread safe since CsrfGuard uses a non concurrent regexpPatternCache.

private final Map<String, Pattern> regexPatternCache = new HashMap<>();

java.util.ConcurrentModificationException: null
      at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)
      at org.owasp.csrfguard.CsrfValidator.isUriRegexMatch(CsrfValidator.java:190)
      at org.owasp.csrfguard.CsrfValidator.isUriMatch(CsrfValidator.java:179)
      at org.owasp.csrfguard.CsrfValidator.isUriMatch(CsrfValidator.java:132)
      at org.owasp.csrfguard.CsrfValidator.isProtectedPage(CsrfValidator.java:93)
      at org.owasp.csrfguard.CsrfValidator.isProtectedPageAndMethod(CsrfValidator.java:79)
      at org.owasp.csrfguard.CsrfValidator.isProtectedPageAndMethod(CsrfValidator.java:145)
      at org.owasp.csrfguard.CsrfValidator.isValid(CsrfValidator.java:65)
      at org.owasp.csrfguard.CsrfGuardFilter.handleNoSession(CsrfGuardFilter.java:111)
      at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:82)
      at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:61)

Switching to ConcurrentHashMap should do the Job.

Impacted jars by Apache Log4j Tool : Zero Day in Ubiquitous Under Active Attack (CVE-2021-44228) ??

Hi Team,

We are using following jar provided by you.
1- antisamy-1.5.7.jar
2- Owasp.CsrfGuard.jar

We want to ensure and know if it is impacted by “Apache Log4j Tool : Zero Day in Ubiquitous Under Active Attack (CVE-2021-44228)”. If it’s impacted please let us know about the security recommendation. To know we are looking for following answer

Are you using log4J?
If you are using log4j 1.x version, are you using JMSAppender class
if you are using log4j 2.x are , what is your security recommendation to fix the issue

Ability to extend CsrfGuardFilter

We have a scenario where we want to skip CSRF guard evaluation based on some parameters in the request. It could be authentication mechanism or any other.
CsrfGuardFilter is a final class and so cannot be extended to write our custom logic before the filter is being evaluated. Thus,
Requesting to make it a non-final class so that we can extend to add custom logic before the filter logic gets executed.

JDK version and TLS protocol errors and solutions

Two errors when running mvn clean install and the solutions

Error 1: JDK 6 not supported
Error message:

$ java -version
java version "1.8.0_251"
Java(TM) SE Runtime Environment (build 1.8.0_251-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.251-b08, mixed mode)

$ mvn clean install
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.219 s
[INFO] Finished at: 2020-05-19T14:41:11+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project csrfguard: Compilation failure
[ERROR] Failure executing javac,  but could not parse the error:
[ERROR] warning: [options] bootstrap class path not set in conjunction with -source 6
[ERROR] error: Source option 6 is no longer supported. Use 7 or later.
[ERROR] error: Target option 6 is no longer supported. Use 7 or later.
[ERROR] 
[ERROR] 
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Solution:
Use older JDK versions by setting JAVA_HOME environment variable.

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

Error 2: TLS version
Error message:

$ java -version

javax.net.ssl.SSLException: Received fatal alert: protocol_version

Solution: Set TLS version to TLSv1.2

export JAVA_TOOL_OPTIONS="-Dhttps.protocols=TLSv1.2"' 

Explanation: https://stackoverflow.com/questions/16541627/javax-net-ssl-sslexception-received-fatal-alert-protocol-version

request through a proxyPass problem

As explained in the pull-request #254, the library fails with a web server served by a proxyPass. The user receives this message: "a OWASP CSRFGuard JavaScript was included from within an unauthorized domain".
More details in the pull request.

(Excuse me if the pull request was enough and this ticket useless)

NullPointerException for Javascript related settings

Describe the bug
We recently upgraded to version 4.1.2 but we now gets NullPointerExceptions in the JavascriptServlet (when the JavaScript itself is requested). When the application is started (or actually when the JavascriptServlet is initialized) all works fine. When the JavaScript is loaded after 2 minutes or more, a NullPointerException is thrown.

Exception type: java.lang.NullPointerException
Stack trace:
org.owasp.csrfguard.servlet.JavaScriptServlet.writeJavaScript(JavaScriptServlet.java:242)
org.owasp.csrfguard.servlet.JavaScriptServlet.doGet(JavaScriptServlet.java:144)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

I think the error is related to the changes for issue #54.
In version 4.1.1 the method javascriptInitParamsIfNeeded was called each time that one of the JavaScript related settings was accessed. This logic is removed in 4.1.2 and the initialization of the JavaScript settings is now done only once when the JavascriptServlet is initialized. The ConfigurationProvider instance however is cached in an expirable cache in the CsrfGuard class. When the configuration expires and a new ConfigurationProvider object is created, the initialization of the JavaScript related settings is not invoked.
When the JavaScript settings are not initialized, the value for the 'Javascript Reference Pattern' setting will be null. The code on line 242 of the JavaScriptServlet calls the getPattern method from the Pattern instance, but this value is null.

To Reproduce

  1. Deploy the csrfguard-test-jsp webapp
  2. Go to http://localhost:8080/javascript.html
  3. The page and the CSRF JavaScript should be loaded correctly
  4. Wait for at least 2 minutes (it looks that the ExpirableCache class only checks for expired items after 2 minutes)
  5. Reload the HTML page
  6. The Javascript servlet will throw a 500 error as in the attached log: Console logging csrfguard-test-jsp.log

Expected behavior
The JavaScript settings must be initialized correctly even when the configuration is reloaded.

Please find a possible solution for this issue in PR #78.

CSRF Guard 4.1.3 - Invalid session error when used with apache and weblogic server, particularly only on Browser Edge in IE 11 Mode

We have recently migrated to the CSRF 4.1.3 from older version 3.1.0 , After having this implemented , we have started facing error specifically on Edge browser over IE-11 Mode.

We are using apache server beneath weblogic server, we are not able to figure out the real root cause, but reverting back CSRF guard to older version 3.1.0 fixed this.

Important Note - It is happening through Third party application interaction with our application and third party application is using IFRAME, We only have this issue in the EDGE in IE-11 mode , but working on all other browsers. Moreover, On first request everything looks fine and our application page loads in IFRAME, But on second request , the cookie which browser sent does not match the server session ID as cookie sent by browser on second request is different from the initial one, which results in invalid session error. Nevertheless, Reverting back to older CSRF Guard fix everything.

Few questions striking my mind here are -

Does CSRF guard 4.1.3 have a support for IE-11 or EDGE in IE-11 Mode ?
Is there any property to handle this in CSRF guard ?
Is this happening due to apache server configuration ?. which should not be the case because older version is working fine on same apache.
Any other possibility or suggestion?
We love to hear back on this and will definitely appreciate any kind of help or suggestions.

Additional Referer header validation can be bypassed

Referer header validation (an ADDITIONAL security measure) can be bypassed if the attacker instructs the browser not to send it.

<html>
    <head>
        <meta name="referrer" content="no-referrer">
    </head>
...
</html>

Quoting from csrfguard.properties

# Allows the developer to specify a regular expression describing the required value of the
# Referer header. Any attempts to access the servlet with a Referer header that does not
# match the captured expression is discarded. Inclusion of referer header checking is to
# help minimize the risk of JavaScript Hijacking attacks that attempt to steal tokens from
# the dynamically generated JavaScript. While the primary defenses against JavaScript
# Hijacking attacks are implemented within the dynamic JavaScript itself, referer header
# checking is implemented to achieve defense in depth.
org.owasp.csrfguard.JavascriptServlet.refererPattern = .*

Create integration tests

Currently the integration of the solution is manually validated through the test application.

It would be much nicer to automate the scenarios and make it part of the CI build.

Part of: #24

3.1.0 release code here is different to the 3.1.0 jar in Maven Central

There are quite a few differences between the 3.1.0 release here and the 3.1.0 release in Maven Central. Do you think the current 3.1.0 release here on GitHub should be changed to a newer 3.x version number to avoid confusion and possibly publish it to Maven Central under that new version? Thanks.

mavenCentral3 1 0VsGitHub3 1 0

Improve the test coverage

Unit and integration tests should be written to make sure that the functionalities still work as expected. It would limit the possible regression issues caused by new development/refactorings, especially since there are several possible configuration permutations.

Detailed manual testing scenarios, executions flows would be very helpful as well because it could also act as a documentation/functional requirements.

Create maven configuration to automate deployment to OSSRH

To current way of creating a new release:

# the artifacts must be signed using gpg
mvn clean verify -Prelease-sign-artifacts
# prepare the release locally
mvn release:clean release:prepare
# perform the release after making sure that everything looks as expected
mvn release:perform
# push the release
git push origin master
# push the newly created tag
git push origin <tag_name>

The contents of the settings.xml:

<settings>
	<servers>
		<server>
		<id>ossrh</id>
		<username>JIRA_USER_WITH_PERMISSIONS</username>
		<password>JIRA_PASSWORD</password>
		</server>
	</servers>
	<profiles>
		<profile>
			<id>ossrh</id>
			<activation>
			<activeByDefault>true</activeByDefault>
			</activation>
			<properties>
				<gpg.passphrase>PERSONAL_GPG_PASSPHRASE</gpg.passphrase>
			</properties>
		</profile>
	</profiles>
</settings>

IE11 error: startsWith not supported

The normalizeUrl and calculatePageTokenForUri functions in csrfguard.js use a function not supported by IE11: startsWith
For example in the js file there is this:

let normalizedUrl = url.startsWith('/') ? url : '/' + url;

I see that you have already created the function startsWith(s, prefix) but you have not used it in the above instruction (and other places)

External config in js file wrongly evaluated

Describe the bug
Hello,
It looks like the external config variables in csrfguard.js are not properly applied.
I've had this issue with the %TOKENS_PER_PAGE% variable (org.owasp.csrfguard.TokenPerPage property)

To Reproduce
Steps to reproduce the behavior:

  1. Simply set the property org.owasp.csrfguard.TokenPerPage to false
  2. Then navigate to a web page

Expected behavior
The token per page should not be applied (and we shouldn't go inside its code)

Screenshots
Will add a screenshot below on the additional context

Desktop :

  • OS: [windows 10]
  • Browser [chrome]
  • Version [91]

Additional context
When the TokenPerPage property is set to false, the following js code on line 719 is evaluated to if('false') (which is actually true)
image

There you can see the debugger going inside the condition (true or false doesnt matter) :
image

So I think you should rollback to what was done in csrfguard 3 : if(%TOKENS_PER_PAGE% == true)
(Or maybe just : if(%TOKENS_PER_PAGE%) )

I think the other conditions have the same issue but I haven't checked

Thank you

charset encoding is missing from JavaScriptServlet responses

Automated scanning tools complain that csrfguard is not setting a charset in the content-type:

Description: | The encoding hasn't been declared either through the meta-tag, the byte-order-mark or the header, so the browser will make an attempt to detect the document's encoding. This exploit only works if the document reflects user input and the browser can be tricked into encoding the page as UTF-7 instead of UTF-8. Some of the browsers actually support UTF-7.

Recommendations: | Always declare the encoding of your document. Use the HTTP header if you can. Always use an in-document declaration too. You can use @charset or HTTP headers to declare the encoding of your style sheet, but you only need to do so if your style sheet contains non-ASCII characters and, for some reason, you can't rely on the encoding of the HTML and the associated style sheet to be the same. Try to avoid using the byte-order mark in UTF-8, and ensure that your HTML code is saved in Unicode normalization form C (NFC).

In order to stop the browser from attempting to detect the encoding (and potentially getting it wrong?) it should be explicitly defined.

The "TokenPerPage" approach is not applied to AJAX requests

The current logic generates and returns new, unique tokens for every accessed URI lazily, but they are only injected into forms or src and href attributes by the injectTokens method. This way a large SPA application using exclusively XHR requests would only make use of one single (session) token.

Master csrf token incorrectly returned as page token

Discussed in #257

Originally posted by musaka872 March 27, 2024
Hi,
I'm trying to integrate csrfguard 4.3.0 in our project.
I've configured it to use per-session tokens and not per-page tokens. But when I receive the token in the response header it is returned as page token in this form {pageTokens:{"/page/uri":"csrf-token"}} and then when I send this token in a subsequent request csrfguard compares {pageTokens:{"/page/uri":"csrf-token"}} to "csrf-token" and it fails.
I debugged CsrfGuardFilter and in handleSession method we have:

private void handleSession(final HttpServletRequest httpServletRequest, final InterceptRedirectResponse interceptRedirectResponse, final FilterChain filterChain,
                               final LogicalSession logicalSession, final CsrfGuard csrfGuard) throws IOException, ServletException {

        final String logicalSessionKey = logicalSession.getKey();

        if (new CsrfValidator().isValid(httpServletRequest, interceptRedirectResponse)) {
            filterChain.doFilter(httpServletRequest, interceptRedirectResponse);
        } else {
            logInvalidRequest(httpServletRequest);
        }

        final String requestURI = httpServletRequest.getRequestURI();
        final String generatedToken = csrfGuard.getTokenService().generateTokensIfAbsent(logicalSessionKey, httpServletRequest.getMethod(), requestURI);

        CsrfGuardUtils.addResponseTokenHeader(csrfGuard, httpServletRequest, interceptRedirectResponse, new TokenTO(Collections.singletonMap(requestURI, generatedToken)));
    }

In generateTokenIfAbsent it checks whether the per-page or master token should be generated and generates the correct master token. But then as you can see when TokenTO is created the master token is passed as per-page token and it is send as such in the response header.

Is this a bug or I'm missing something?

I don't want to parse the response header to retrieve the "csrf-token" that csrfguard returns.

Best regards,
Martin

Usage of XMLHttpRequest in a WebComponent with Google Polymer 1.x

This is an interesting project, thank you for your time building it.

One question that i have: What configuration is needed for XMLHttpRequest in a WebComponent context.

I have a single page application, which uses Google Polymer 1.x (https://polymer-library.polymer-project.org/1.0/docs/devguide/feature-overview). This has a WebComponent iron-ajax (https://github.com/PolymerElements/iron-ajax/tree/1.x), which uses XMLHttpRequest internally.

I was able to configure my project to using "Scenario: everything is protected, except...".

In some cases it works, and then suddenly the request token is not updated, generating "Request Token does not match Page Token". If i use TokenPerPage=true, then my issues are gone, but i am wondering if this makes the solution less secure.

Empty token after login

Hello, I have implemented this library in a Spring (4.0.1) project, and it's working properly until the user logs in, when the javascript injects an empty string as the token. If I refresh the page or logout it loads another token (here are some screenshots). I've tested with different settings but still the same, any idea what I can look into?

This is the configuration currently used:

************************************************************
* OWASP CSRFGuard properties
* Actions: 
	* org.owasp.csrfguard.action.Redirect
		* Parameter: Page = /{ProjectName}/error.html
	* org.owasp.csrfguard.action.Log
		* Parameter: Message = Potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
	* org.owasp.csrfguard.action.Rotate
* Ajax: true
* Banned User Agent Properties: 
	* msie
	* trident
* Enabled: true
* Force Synchronous Ajax: false
* Is Javascript Inject Into Dynamically Created Nodes: false
* Javascript Domain Strict: false
* Javascript Inject Form Attributes: false
* Javascript Inject Get Forms: false
* Javascript Inject Into Attributes: false
* Javascript Inject Into Forms: false
* Javascript Params Initialized: false
* Javascript Referer Match Domain: false
* Javascript Referer Match Protocol: false
* Logical Session Extractor: org.owasp.csrfguard.session.SessionTokenKeyExtractor
* Page Token Synchronization Tolerance: 2000 ms
* Print Config: true
* Prng: java.security.SecureRandom(algorithm: SHA1PRNG, provider: SUN version 1.8)
* Protect: false
* Protected Methods: 
	* DELETE
	* POST
	* GET
	* PUT
* Rotate: false
* Token Holder: org.owasp.csrfguard.token.storage.impl.InMemoryTokenHolder
* Token Length: 32
* Token Name: OWASP-CSRFTOKEN
* Token Per Page: false
* Token Per Page Precreate: false
* Unprotected Pages: 
	* *.png
	* *.ttf
	* *.gif
	* *.svg
	* *.css
	* *.html
	* *.jpg
	* *.js
* Use New Token Landing Page: false
* Validation When No Session Exists: true
************************************************************

Thanks.

Ability to configure multiple values for org.owasp.csrfguard.domainOrigin

Discussed in #169

Originally posted by bpapez January 24, 2023
We have a requirement for being able to configure multiple values for the org.owasp.csrfguard.domainOrigin property. It could either be a regular expression, like:

org.owasp.csrfguard.domainOrigin = example.(ch|swiss)

or a list like:
org.owasp.csrfguard.domainOrigin = example.ch,example.swiss

As far as I can see this value is only used as parameter in the isValidDomain function of csrfguard.js . Should we provide a PR to handle multiple values in the original csrfguard.js or do you think this should just be solved in custom adaptations? Which solution do you prefer, the regexp or the list?

Regards,
Benjamin

NullPointerException when using JSP Tags and the CSRFGuard is disabled.

Hello,

[Bug Description]
I am using CSRFGuard JSP Tag libraries in a Java EE project (Java 8). I recently faced the following issue: when I have to set the org.owasp.csrfguard.Enabled property to false, then a Null Pointer Exception is thrown and my application fails to load.

I checked the code of the respective JSP Tags and noticed that there is no check to see if the CSRFGuard is enabled before proceeding with the token injection. After debugging I found that the following line throwsthe exception:

final LogicalSession logicalSession = csrfGuard.getLogicalSessionExtractor().extract((HttpServletRequest) this.pageContext.getRequest());

[To Reproduce]
Steps to reproduce the behavior:

  1. Go to CSRFGuard properties and set org.owasp.csrfguard.Enabled = false
  2. Load any page that is using CSRFGuard JSP Tags
  3. See the error in the logs

[Expected behavior]
Due to practical reasons, I deem necessary to find a solution so that the application using CSRFGuard tags would not be impacted by CSRF functionality when the guard is disabled.

[Environment]

  • OS: RHEL
  • Browser: Chrome, Firefox (I checked only those two)

[Solution that worked for me]
If you would like to consider my solution, I have submitted a Pull Request with the branch check_if_enabled_before_injecting_with_tag which contains a simple solution by checking if the CSRFGuard is enabled before proceeding with the logic. I have done this for TokenTag, TokenNameTag, TokenValueTag.

Redirect functionality on invalid or no token in request

I understand that when a request comes into my application, against an endpoint I have protected, with either no token or an invalid token that this library will perform a redirect to my configured error page/endpoint.

I was recently testing an application that was using v3.1.0 of this library and they had setup /home to be their configured error endpoint. The functionality within this controller was to redirect to another (protected) endpoint within the application. This internal redirect would work. Upgrading the CSRFGuard library to the latest version causes this behavior to (as expected) result in an infinite loop.

Why did this functionality change between v3.1.0 and the current version? Was it just a functional change or to remediate against a vulnerability?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.